我想使用多个角色来访问应用程序中的视图,如果我使用一个角色,则一切正常,但是当我使用多个角色时,视图不提供访问权限
我的模特用户拥有此:
export class User {
role: Role; // I change - role: Role[] for few roles
expiresIn: string;
aud: string;
iss: string;
token?: string;
}
export enum Role {
Admin = 'admin',
User = 'user',
Engineer = 'engineer'
}
我的后端给我的令牌和角色:
//....
role: (2) ["admin", "engineer"]
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ
//....
如果我在登录方式中使用此选项
tokenInfo['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'][0] - first element in array
我只有一个角色,并且代码工作正常,但是我可以有许多属于不同角色的用户,并且如果至少有一个角色,我需要应用程序为他们提供访问权限
我处理令牌解码并获得授权服务中的角色
signin(username:string, password:string ) {
return this.http.post<User>(`${environment.apiUrl}${environment.apiVersion}Profile/Login`, {username, password})
.pipe(map(user => {
if (user && user.token) {
let tokenInfo = this.getDecodedAccessToken(user.token); // decode token
this.session = {
token: user.token,
role: tokenInfo['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'], - add this [0]
expiresIn: tokenInfo.exp,
aud: tokenInfo.aud,
iss: tokenInfo.iss,
}
localStorage.setItem('currentUser', JSON.stringify(this.session));
this.currentUserSubject.next(this.session);
}
return this.session;
}))
}
例如简单的脚架
Login() {
this.auth.signin(this.signinForm.value.email, this.signinForm.value.password)
.pipe(first())
.subscribe(
data => {
console.log("User is logged in");
this.router.navigate(['/dashboard']);
this.loading = false;
});
}
不确定我是否正确指定了多个访问角色
//......
{
path: 'books',
loadChildren: () => import('./views/books/books.module').then(m => m.BooksModule),
canActivate: [AuthGaurd],
data: { roles: [Role.Admin] } <- work fine if 1 role
},
{
path: 'person',
loadChildren: () => import('./views/person/person.module').then(m => m.PersonModule),
canActivate: [AuthGaurd],
data: { roles: [Role.Admin, Role.Engineer] } <- if have 1 role - admin - open
},
{
path: 'eqip',
loadChildren: () => import('./views/person/person.module').then(m => m.PersonModule),
canActivate: [AuthGaurd],
data: { roles: [Role.Engineer] } <- not open becouse only admin role
},
//......
也可能是打字稿枚举不是字符串。因此,将enum
与字符串进行比较将永远是不正确的。
您需要使用const enum
,因为它会编译为字符串。
尝试更改为
export const enum Role {
Admin = 'admin',
User = 'user',
Engineer = 'engineer'
}
尽管这确实具有其他含义。https://www.typescriptlang.org/docs/handbook/enums.html#const-enums
这实际上取决于您如何处理AuthGuard代码。本指南中提供了有关如何设置身份验证和授权的综合教程:https://jasonwatmore.com/post/2018/11/22/angular-7-role-based-authorization-tutorial-with-example
AuthGuard
上可能会遇到问题的较大区域。您可以从我上面共享的链接中获得此示例:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthenticationService } from '@/_services';
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(
private router: Router,
private authenticationService: AuthenticationService
) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const currentUser = this.authenticationService.currentUserValue;
if (currentUser) {
// check if route is restricted by role
if (route.data.roles && route.data.roles.indexOf(currentUser.role) === -1) {
// role not authorised so redirect to home page
this.router.navigate(['/']);
return false;
}
// authorised so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
return false;
}
}
您还需要确保将正确的角色传递到AuthGuard
中。
如果您以后希望有更严格的限制,也可以参考以下指南:How to prevent actions by user role in Angular
希望这会有所帮助!