Web应用程序项目中Angular 13中的授权问题

Posted

技术标签:

【中文标题】Web应用程序项目中Angular 13中的授权问题【英文标题】:Problem with authorization in Angular 13 in web-app project 【发布时间】:2021-12-28 11:10:11 【问题描述】:

我在 Angular 13 版本的项目中遇到授权问题。在 angular 10 中一切正常,但是当我将项目从 angular 10 升级到 angular 13 时,我收到了一个失败,如下图所示 enter image description here

以下是我的 TokenStorage 类代码:

import  Injectable  from '@angular/core';
const TOKEN_KEY = 'AuthToken';
const USERNAME_KEY = 'AuthUsername';
const AUTHORITIES_KEY = 'AuthAuthorities';

@Injectable()
export class TokenStorage 

     roles: string[] = [];
    constructor()

    signOut()
        window.sessionStorage.removeItem(TOKEN_KEY);
        window.sessionStorage.clear();
        this.reloadPage();
    

    public saveToken(token: string)
        window.sessionStorage.removeItem(TOKEN_KEY);
        window.sessionStorage.setItem(TOKEN_KEY, token);
    

    public getToken(): string 
        return sessionStorage.getItem(TOKEN_KEY);
    

    public saveLogin(login: string)
        window.sessionStorage.removeItem(USERNAME_KEY);
        window.sessionStorage.setItem(USERNAME_KEY, login);
    

    public getLogin(): string
        return sessionStorage.getItem(USERNAME_KEY);
    

    public saveAuthority(authorities: string[])
        window.sessionStorage.removeItem(AUTHORITIES_KEY);
        window.sessionStorage.setItem(AUTHORITIES_KEY, JSON.stringify(authorities))
    

    public getAuthority(): string[] 
        this.roles = []
        if (sessionStorage.getItem(TOKEN_KEY)) 
          JSON.parse(sessionStorage.getItem(AUTHORITIES_KEY)!).forEach(authority => 
            this.roles.push(authority.authority);
          );
        
        return this.roles;
    
    
    public isUserSignedIn() : boolean 
        if(this.getToken())
            return true;
        
        return false;
    

    reloadPage(): void
        window.location.reload();
    

这是拦截器类代码:

import  Injectable  from '@angular/core';
import HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent,
  HttpResponse, HttpUserEvent, HttpErrorResponse from '@angular/common/http';
import  Observable  from 'rxjs';
import  Router  from '@angular/router';
import TokenStorage from './token.storage';
import tap from "rxjs/operators";

const TOKEN_HEADER_KEY = 'Authorization';

@Injectable()
export class Interceptor implements HttpInterceptor 

  constructor(private token: TokenStorage, private router: Router)  

  intercept(req: HttpRequest<any>, next: HttpHandler):
    Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> 
    let authReq = req;
    if (this.token.getToken() != null) 
      authReq = req.clone( headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + this.token.getToken()));
    

     return next.handle(authReq).pipe( tap(() => ,
     (err: any) => 
     if (err instanceof HttpErrorResponse) 
       if (err.status !== 401) 
        return;
       
     
   ));

  


这里是 auth.service 代码:

import  Observable, throwError  from 'rxjs';
import  Injectable  from '@angular/core';
import  HttpClient, HttpHeaders, HttpErrorResponse  from '@angular/common/http';
import  catchError  from 'rxjs/operators';

@Injectable()
export class AuthService 

 private watkrewUrl = "http://localhost:8080/";

  constructor(private _http: HttpClient)  
  

  login(login: string, password: string): Observable<any> 
    const credentials = login: login, password: password;
    return this._http.post<any>(this.watkrewUrl + "signin", credentials).pipe(
      catchError((err: HttpErrorResponse) => 
        return throwError(err.error.message);
        console.log(err.message)
      
      ))
  

  register(login: string, password: string, email: string, name: string, surname: string, role: string): Observable<any>
    const signupForm = login: login, password: password, email:email, name:name, surname: surname, role: role
    return this._http.post<any>(this.watkrewUrl + "signup", signupForm).pipe(
      catchError((err: HttpErrorResponse)=> 
        return throwError(err.error.message);
      )
    )
  


有人知道如何解决这个问题吗?

【问题讨论】:

【参考方案1】:

SessionStorage.getKey 返回string | null。 但是,您的 TokenStorage.getToken 方法会根据您的签名返回 string

如果您确定会话存储始终包含此密钥,则可以在不更改 TokenStorage.getToken 签名的情况下执行以下操作之一。 a) 将 string | null 转换为 string 就像 sessionStorage.getItem(TOKEN_KEY) as string b) 检查null,如果值为null,则抛出错误

    public getToken(): string 
        const value = sessionStorage.getItem(TOKEN_KEY);
        if (!value) 
            throw Error('Type a message here');
        
        return value;
    

否则,您必须将 TokenStorage.getToken 返回类型更改为 string | null

【讨论】:

以上是关于Web应用程序项目中Angular 13中的授权问题的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6 对 .NET Web API 的跨域 POST 请求返回 401(未经授权)

Angular MSAL AD 401 在 Angular 应用程序中未经授权,但在 Postman 中 200 正常 - ASP.NET Core Web API

Angular 5:从拦截器中的 http 响应标头获取授权

Angular 中的不记名令牌

.NET 5 Web API 中的 JWT 授权和刷新令牌

从使用 Angular 7 的请求中接收 Spring Boot 中的空授权标头,但 Postman 工作正常