【问题标题】:Angular 6 - roles/claims based auth guard not workingAngular 6 - 基于角色/声明的身份验证防护不起作用
【发布时间】:2019-01-19 22:17:03
【问题描述】:

我的应用中经过身份验证的用户可以有多个角色,因此,我想根据用户的特定角色来保护路由。我在AuthGuardService 中包含了checkAuthentication() 方法中的角色检查,然后在路由模块中应用data: { roles: ['USER'] }。我还在 store 中设置了identity 来检测AuthService 中路由保护的角色。但是,当我尝试登录时,它不会路由到仪表板,而是停留在登录页面,即使我可以看到本地存储中设置的令牌。

路由模块:

  {
    path: 'home', component: HomeComponent, canActivate: [AuthGuardService], data: { roles: ['PRIMARY, SUBSTITUTE'] },
    children: [
      { path: '', redirectTo: 'offers', pathMatch: 'full' },
      { path: 'offers', component: OffersComponent, data: { roles: ['PRIMARY, SUBSTITUTE'] }, canActivateChild: [AuthGuardService] },
      { path: 'users', component: UsersComponent, data: { roles: ['PRIMARY'] }, canActivateChild: [AuthGuardService] },
      { path: 'settings', component: SettingsComponent, data: { roles: ['PRIMARY, SUBSTITUTE, USER'] },
        canActivateChild: [AuthGuardService] }
    ]
  }

身份验证服务:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    const url: string = state.url;
    return this.checkAuthentication(url, state, route.data['roles']);
  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.canActivate(route, state);
  }

  checkAuthentication(url: string, state, requiredRoles: string[]) {
    return this.authService.roles$.pipe(
      flatMap((roles: string[]) => {
        for (const role of requiredRoles) {
          if (roles.includes(role) && this.authService.hasValidToken()) {
            return of(true);
          } else if (roles.includes(role) && this.authService.hasValidToken() === false) {
            return this.authService.refreshToken().pipe(
              map((tokens: AuthToken) => {
                if (tokens.authToken) {
                  // refresh token successful
                  return true;
                }
                // refresh token did not succeed
                this.authService.logout();
                this.router.navigate(['']);
                return false;
              },
                error => {
                  this.authService.logout();
                  this.router.navigate(['']);
                  return of(false);
                })
            );
          }
        }
        this.router.navigate(['']);
        return of(false);
      })
    );
  }

身份验证服务:

private roles = new BehaviorSubject([]);
  public roles$ = this.roles.asObservable();

  private identity = new BehaviorSubject(<Identity>{});
  public identity$ = this.identity.asObservable();

  constructor(
    private store: Store<AppState>
  ) {
    this.store.select('tokens').subscribe((tokens: AuthToken) => {
      this.tokens = tokens;
    });

    this.store.select('identity').subscribe((identity: any) => {
      console.log(identity);
      if (identity.identity && identity.identity.roles) {
        this.setIdentity(identity.identity);
        this.setRoles(identity.identity.roles);
      } else {
        this.setRoles([]);
      }
    });
  }

  setRoles(roles: any[]) {
    this.roles.next(roles);
    console.log(roles);
  }

  setIdentity(identity: Identity) {
    this.identity.next(identity);
    console.log(identity);
  }

【问题讨论】:

    标签: angular routing jwt auth-guard


    【解决方案1】:

    请参阅stackblitz 中的此示例

    在您的 app-routing.module.ts 中

    const routes: Routes = [
       {
           path: "admin",
           component: AdminOnlyComponent,
           canActivate: [RoleGuardService],
           data: { roles: ['admin']}
       },
       ...
    }
    

    在您的 RoleGuardService 中

    import { Injectable } from '@angular/core';
    import { UserRolesService} from './user-roles.service';
    import { Router, ActivatedRouteSnapshot } from '@angular/router';
    @Injectable({
      providedIn: 'root'
    })
    export class RoleGuardService {
    
      constructor(private getUserRoles: UserRolesService) { }
    
      canActivate(route: ActivatedRouteSnapshot): boolean {
        return route.data.roles.some( ai => this.getUserRoles.getRoles().includes(ai) );
      }
    }
    

    在用户角色服务中

    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class UserRolesService {
       userRoles: string[] = [];
    
      constructor() { }
    
      setRoles(Roles: string[]){
        this.userRoles = Roles.slice(0);
      }
    
      getRoles(){
        return this.userRoles;
      }
    }
    

    在用户登录系统时设置角色或从本地存储中获取这些角色....

    希望这会有所帮助..

    【讨论】:

      【解决方案2】:

      我有同样的问题。您可以尝试以下方法

      1. 复制令牌并在此处检查 https://jwt.io/ 并验证令牌是否包含您期望的角色(区分大小写)。

      2. 而且,当你有多个角色时,它会出现在一个数组中,但当它是单个角色时,它是一个字符串。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        • 2012-12-12
        • 2020-03-13
        • 1970-01-01
        • 2018-07-12
        • 2020-12-21
        • 2015-04-09
        相关资源
        最近更新 更多