我的应用程序中经过身份验证的用户可以具有多个角色,因此,我想根据用户的特定角色来保护路由。我在checkAuthentication()
的方法AuthGuardService
中加入了角色检查,然后在路由模块中应用了data: { roles: ['USER'] }
。我还在存储中设置了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] }
]
}
auth-guard-service:
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);
}
答案 0 :(得分:0)
我有同样的问题。您可以尝试以下
复制令牌并在此处https://jwt.io/进行检查,并验证令牌是否包含您期望的角色(区分大小写)。
而且,当您具有多个角色时,它似乎出现在数组中,但当它是单个角色时,它是一个字符串。
答案 1 :(得分:0)
请参见stackblitz
中的示例在您的app-routing.module.ts
remDr$navigate("https://...")
remDr$refresh()
在您的RoleGuardService中
const routes: Routes = [
{
path: "admin",
component: AdminOnlyComponent,
canActivate: [RoleGuardService],
data: { roles: ['admin']}
},
...
}
在UserRolesService中
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) );
}
}
在用户登录系统时设置角色,或从您的本地存储中获取这些角色。...
希望这会有所帮助。