带有 jwt cookie 的 Angular 应用程序中的身份验证点

Posted

技术标签:

【中文标题】带有 jwt cookie 的 Angular 应用程序中的身份验证点【英文标题】:Point of authentication in an angular application with jwt cookie 【发布时间】:2021-12-27 21:10:13 【问题描述】:

我无法找到解决我的具体问题的现有问题。我正在开发一个 angular 应用程序,它使用 jwt 和 http-only cookie 进行身份验证。像往常一样,为了验证后端的请求,jwt cookie 随每个请求一起发送。一切正常,但我想知道验证用户是否通过身份验证的最佳方法是什么——尤其是WHERE

从各种教程中,我知道您通常使用 AuthGuards 和自定义 AuthService 来验证身份验证和保护路由。在我的情况下,我可以通过提供端点 /api/users/currentuser 来验证身份验证,其唯一目的是检查 jwt 令牌并在用户通过身份验证时使用用户对象回答。这也可以正常工作,但是在 Angular 应用程序中触发该请求的最佳位置在哪里?

它是否在我的 AuthServiceconstructor 中,以确保它是第一个被调用的东西,然后设置一个所有其他组件都可以订阅的 BehaviorSubject<boolean>

 export class AuthService 
 isLoggedIn$ = new BehaviorSubject < boolean > (this.isLoggedIn);
 ...
 constructor() 
   // make call to /api/users/currentuser backend 
   // set isLoggedin$ to true/false according to result of currentuser response
   this.isLoggedIn$.next(value);
 

保护一个或多个路由的 AuthGuard 是否应该向canActivate 内部的后端发出自己的请求?

 canActivate(
     route: ActivatedRouteSnapshot,
     state: RouterStateSnapshot
   ):
     | Observable<boolean | UrlTree>
     | Promise<boolean | UrlTree>
     | boolean
     | UrlTree 
     if (!this.authService.getCurrentUser()) 
       console.log('NOT autheticated');
       this.router.navigate(['']);
       return false;
     

     console.log('AUTHENTICATED');
     return true;
   

或者 AuthGuard 订阅AuthService BehaviorSubject 应该像这样:

 canActivate(
     route: ActivatedRouteSnapshot,
     state: RouterStateSnapshot
   ):
     | Observable<boolean | UrlTree>
     | Promise<boolean | UrlTree>
     | boolean
     | UrlTree 
     if (!this.authService.isLoggedIn$.getValue()) 
       console.log('auth guard NOT autheticated');
       this.router.navigate(['']);
       return false;
     

     console.log('AUTHENTICATED');
     return true;
   

是否应该在页面加载开始时使用async ... await ... 调用/api/users/currentuser,以确保在同时呈现页面之前验证身份验证?

尤其是在页面刷新之后 - 理想的身份验证魔法应该在哪里发生?

应用程序中是否有一个完美的地方/点应该发生一次呼叫?/api/users/currentuser?并且所有需要知道身份验证信息的组件可以共享结果,或者应该出于(安全?)原因从各个地方(authservice、authguard、不同组件等)多次调用?

当前 app.component.html

<app-navbar></app-navbar>
<router-outlet></router-outlet>

【问题讨论】:

【参考方案1】:

理想情况下,您(可能是大多数人)希望在应用程序中的任何其他操作之前进行身份验证。这意味着最好的办法是作为一些“预加载”服务的一部分。

创建如下服务:

@Injectable(
    providedIn: 'root',
)
export class PreloadService
    constructor(
        private authService: AuthService
        // add whatever other imports needed
    ) 

    public async initializeApp() 
        if (!this.authService.isLoggedIn()) 
            await this.authService.login() // or whatever you need to do
             
    


export function PreloadFactory(preloadService: PreloadService) 
    return () => preloadService.initializeApp();

然后在app.module中:

    providers: [
        
            provide: APP_INITIALIZER,
            useFactory: PreloadFactory,
            deps: [PreloadService],
            multi: true,
        ,
    ]

现在您的预加载服务将运行,并且可以确保在应用初始化时以及在任何路由加载之前对用户进行身份验证。

【讨论】:

感谢您非常的快速响应!我假设在this.authService.login() 中,我将一个布尔 BehaviorSubject (如“isAuthenticated”)设置为 true,所有其他组件都可以订阅? @woody_cms 通常您不需要其他组件来订阅它。在预加载中,您可能会创建某种用户对象或类似的东西,其中包含 JWT 等。如果用户无法进行身份验证,那么会有一个标志表明用户无效等。然后你会在需要用户登录的任何路由上都有一个RouteGuard,您将检查用户对象,并将它们转发到该实例中的登录页面。

以上是关于带有 jwt cookie 的 Angular 应用程序中的身份验证点的主要内容,如果未能解决你的问题,请参考以下文章

Cookie 中的 Angular JWT 如何防止 CSRF/XSRF 和 XSS

Angular 和 PHP JWT 和 CSRF (XSRF) Cookie

Angular 对 JWT 使用展位 cookie 或拦截器有用吗?

将 JWT 存储在基于会话的 cookie Angular 6 中

httpOnly cookie 中的 JWT - AuthGuard 和受保护的路由(Node.js、Angular)

无法使用 Express 和 Angular 将 JWT 存储在 Cookie 中