从前端发送的授权令牌不起作用(JWT)

Posted

技术标签:

【中文标题】从前端发送的授权令牌不起作用(JWT)【英文标题】:Authorization token sent from frontend doesn't works (JWT) 【发布时间】:2021-04-21 00:38:55 【问题描述】:

登录/注册过程正常,但我无法使用@secured 或@preauthorize 注释访问端点。

LOGS IN CONSOLE(spring app):“未经授权的错误:访问此资源需要完全身份验证”。

使用 POSTMAN 可以正常工作,所以这是前端的问题。

角度:

_helper

import  HTTP_INTERCEPTORS, HttpEvent  from '@angular/common/http';
import  Injectable  from '@angular/core';
import  HttpInterceptor, HttpHandler, HttpRequest  from '@angular/common/http';

import  TokenStorageService  from '../_services/token-storage.service';
import  Observable  from 'rxjs';

const TOKEN_HEADER_KEY = 'Authorization';       // for Spring Boot back-end

@Injectable()
export class AuthInterceptor implements HttpInterceptor 
  constructor(private token: TokenStorageService)  

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    let authReq = req;
    const token = this.token.getToken();
    if (token != null) 
      authReq = req.clone( headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) );
    
    return next.handle(authReq);
  


export const authInterceptorProviders = [
   provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true 
];

_services

import  Injectable  from '@angular/core';

const TOKEN_KEY = 'auth-token';
const USER_KEY = 'auth-user';

@Injectable(
  providedIn: 'root'
)
export class TokenStorageService 

  constructor()  

  signOut(): void 
    window.sessionStorage.clear();
  

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

  public getToken(): string | null 
    return window.sessionStorage.getItem(TOKEN_KEY)
  

  public saveUser(user: any): void 
    window.sessionStorage.removeItem(USER_KEY);
    window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
  

  public getUser(): any 
    const user = window.sessionStorage.getItem(USER_KEY);
    if (user) 
      return JSON.parse(user);
    

    return ;
  


组件示例(针对用户)

import  Component, OnInit  from '@angular/core';
import  AuthService  from '../_services/auth.service';
import  TokenStorageService  from '../_services/token-storage.service';

@Component(
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
)
export class LoginComponent implements OnInit 
  form: any = 
    username: null,
    password: null
  ;
  isLoggedIn = false;
  isLoginFailed = false;
  errorMessage = '';
  roles: string[] = [];

  constructor(private authService: AuthService, private tokenStorage: TokenStorageService)  

  ngOnInit(): void 
    if (this.tokenStorage.getToken()) 
      this.isLoggedIn = true;
      this.roles = this.tokenStorage.getUser().roles;
    
  

  onSubmit(): void 
    const  username, password  = this.form;

    this.authService.login(username, password).subscribe(
      data => 
        this.tokenStorage.saveToken(data.token); //token
        this.tokenStorage.saveUser(data);

        this.isLoginFailed = false;
        this.isLoggedIn = true;
        this.roles = this.tokenStorage.getUser().roles;
        this.reloadPage();
      ,
      err => 
        this.errorMessage = err.error.message;
        this.isLoginFailed = true;
      
    );
  

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

更新: 在调试器中运行 spring 应用程序后,我得到了这个: ((UsernamePasswordAuthenticationToken)authentication).authorities = 找不到局部变量'authentication'

spring boot 应用中有 AuthJwt 代码:

@Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException 
        logger.error("Unauthorized error: ", authException.getMessage());
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
    

【问题讨论】:

const token = this.token.getToken(); debugger; if (token != null) authReq = req.clone( headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) ); 在那里放置一个调试器标签并检查拦截器克隆和修改的请求中的内容 我不知道为什么,但它没有抓住这一点,就好像它从未发生过一样 您是否将AuthInterceptor 添加为AppModule 的提供者?也许将您的AppModule 添加到问题中。我认为还需要将HttpClientModuleBrowserModule 导入到@NgModule 所以...我确实忘记了,非常感谢!现在它可以工作了:) 您介意我将其添加为答案并且您接受它以帮助未来的用户吗? 【参考方案1】:

确保AuthInterceptor 也在AppModule 中声明为提供者。

@NgModule(
  providers: [authInterceptorProviders],
  bootstrap: [AppComponent]
)
export class AppModule  

【讨论】:

以上是关于从前端发送的授权令牌不起作用(JWT)的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP .Net Core 2.2 中添加 JWT 令牌后授权不起作用

使用 OAuth2 保护服务,JWT 令牌不起作用 Spring Cloud

将 jwt 令牌添加到 GET 请求在 React 中不起作用

Spring Security JWT - 通过授权标头的邮递员身份验证有效,但从我的 Angular 前端不起作用

.Net Core 2 JWT,Angular 2 通过角色授权不起作用

在 Volley 请求中添加 JWT 令牌