首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角6 JWT认证

角6 JWT认证
EN

Stack Overflow用户
提问于 2018-10-10 11:26:53
回答 1查看 943关注 0票数 2

我用JWT令牌保护我的角6应用程序。我有一个保护UI元素的auth服务:

代码语言:javascript
复制
export class AuthService {

  constructor(
    private http: HttpClient,
    private router: Router,
    public jwtHelper: JwtHelperService,
  ) {}

  isAuthenticated(): boolean {
    return !this.isTokenExpired;
  }

然后我可以调用我的组件:

代码语言:javascript
复制
<span class="page-nav" *ngIf="!authService.isAuthenticated()">
    <a mat-button routerLink="/login">
        Log In
    </a>
</span>

我也有一个守卫我的路线:

代码语言:javascript
复制
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(): boolean {
    if (!this.authService.isAuthenticated()) {
      this.router.navigate(['/login']);
      return false;
    }
    return true;
  }
}

这一切都很好,除非令牌变得无效,否则当前页面不会路由到login

例如,如果我登录,获得一个有效的JWT令牌,我可以导航到受保护的页面,并显示受保护的UI元素(导航等等)。如果我然后通过chrome工具从本地存储中删除JWT令牌,然后单击导航,受保护的UI元素就会如预期的那样消失,但是受保护的页面将保持不变,路由auth保护不会被调用,只会在导航到另一个页面时将路由路由到login

我尝试过在isAuthenticated() authService方法中路由,但这会导致无限循环。如何在调用login之外自动路由到AuthGuard?

编辑

路由:

代码语言:javascript
复制
const routes: Routes = [
  { path: '', redirectTo: '/products', pathMatch: 'full' },
  {
    path: 'products',
    component: ProductsComponent,
    canActivate: [AuthGuard],
    children: [
      { path: ':id', component: ProductComponent, canActivate: [AuthGuard] },
    ],
  },
  {
    path: 'search',
    component: SearchComponent,
    canActivate: [AuthGuard],
  },
  { path: 'login', component: LoginComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

编辑:我意识到这是预期的行为,作为@GangadharJannu 提及,路由器不知道UI元素已经调用了isAuthenticated()方法,并且在返回false时隐藏起来,直到调用AuthService刷新方法并执行相同的检查。我想知道当UI元素调用login方法时,让路由器知道导航到isAuthenticated()的最佳方法是什么?

编辑:我的工作解决方案:

代码语言:javascript
复制
 import { map } from 'rxjs/operators';
 import { interval } from 'rxjs';
 import { JwtHelperService } from '@auth0/angular-jwt';

 ...

 public validateToken(): void {
    interval(1000).pipe(
      map(() => {
        const isExpired: boolean = this.jwtHelper.isTokenExpired(
          localStorage.getItem('jwt_token'),
        );
        if (isExpired) {
          this.logout();
        }
      }),
    );
  }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-10 12:42:29

我们的父级空状态只是为了保护应用程序的受保护部分,您可能需要尝试一下。尝试如下所示的路由配置:

代码语言:javascript
复制
const routes: Routes = [{ 
    path: '', 
    canActivateChild: [AuthGuard], 
    runGuardsAndResolvers: 'always',
    children: [{
        path: 'products',
        component: ProductsComponent,
        children: [
          { path: ':id', component: ProductComponent },
        ],
      }, {
        path: 'search',
        component: SearchComponent
    }]
  },
  { path: '', redirectTo: '/products', pathMatch: 'full' },
  { path: 'login', component: LoginComponent },
];

注意runGuardsAndResolvers: 'always' -它告诉角总是运行警卫和解析器,即使在导航到相同的状态。

编辑

因此,基本上您希望观察本地存储并对更改作出反应,因此,当令牌从存储中移除或过期时,您希望立即导航到登录组件。一些想法:

  • 您可以将过期检查的频率提高到1s,这不会造成太大的伤害,因为当前您正在检查令牌是否在每个呈现周期过期。
  • 您可以在每次刷新令牌时设置一个可观察的时间,以便在到期后触发一秒钟,并导航到登录。
  • 要观察本地存储本身的变化,可以搜索具有此功能的库(就像这个)或直接使用本机存储更改事件
  • 如果您不关心用户手动删除令牌时的用例,那么当应用程序从本地存储(问题/答案)删除令牌时,您可以导航到登录。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52739186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档