В Angular -> как проверить, есть ли у пользователя разрешение на доступ на основе ролей с сохранением роли в базе данных.
Я пытаюсь сделать ролевый доступ к своему приложению в угловом формате, и мне нужна помощь, потому что я новичок в угловом...
Во-первых, это то, что я имею в маршруте, где я устанавливаю, какие роли могут получить к нему доступ...
из app-routing.module.ts
{
path: 'profile',
component: ComunityComponent,
canActivate: [AuthGuard],
data: {
allowedRoles: ['admin', 'user']
}
},
Во-вторых, я использую функцию canActivate, чтобы проверить, может ли пользователь получить доступ к маршруту или нет. от auth.guard.ts
private hasAccess: boolean;
constructor(private router: Router, private auth: AuthService) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const allowedRoles = next.data.allowedRoles;
if (localStorage.getItem('currentUser')) {
return this.checkAccess(localStorage.getItem('currentUser'), allowedRoles);
}
this.router.navigate(['/login'], {queryParams: {returnUrl: state.url}});
return false;
}
В-третьих, я разрабатываю функцию accessLoginToken, которая найдет роль зарегистрированного пользователя через службу httpclient.get, которая возвращает массив с ролями, назначенными пользователю. пример {success: true, roles:['user']}
из auth.service.ts
accessLoginToken(token: string) {
const check = '/users/access';
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'Bearer ' + token,
})
};
return this.http.get<any>('/api' + check, httpOptions).pipe(
catchError(err => this.handleError('accessLoginToken', err))
);
}
Четвертый в function checkAccess
Я сравниваю это с маршрутом, и если они совпадают, я разрешаю доступ, иначе нет. от auth.guard.ts
private checkAccess(token: string, allowedRoles: string[]): boolean {
this.hasAccess = false;
this.auth.accessLoginToken(token).subscribe(data => {
if (data.success) {
data.roles.forEach(rol => {
if (allowedRoles.findIndex(rols => rols === rol) >= 0) {
this.hasAccess = true;
}
});
}
}, (error) => {
console.log(error);
});
console.log(this.hasAccess);
return this.hasAccess;
}
Основная проблема заключается в том, что я не могу заставить подписку httpclient изменить значение переменной hasAccess на true, чтобы разрешить доступ. Даже когда код this.hasAccess = true;
выполняется функция возвращает false
Кстати, мне не нравится идея сохранения роли в переменной сеанса, такой как access_token, поэтому я пытаюсь сохранить ее в базе данных...
любая помощь по этому вопросу будет оценена.. спасибо
2 ответа
Вы правы, checkAccess
Функция завершается до завершения асинхронного вызова API, поэтому false
всегда возвращается. Вместо этого вы должны передать наблюдаемое методу canActivate.
private checkAccess(token: string, allowedRoles: string[]): boolean {
this.hasAccess = false;
return this.auth.accessLoginToken(token).pipe(
map(data => {
if (data.success) {
data.roles.forEach(rol => {
if (allowedRoles.findIndex(rols => rols === rol) >= 0) {
this.hasAccess = true;
}
});
}
return this.hasAccess;
})
)
}
Поскольку наблюдаемое возвращается к canActivate
Метод, охранник подпишется на наблюдаемое и будет ждать истинного или ложного результата.
Ваша проблема заключается в том, что вы возвращаете this.hasAccess, пока accessLoginToken все еще работает. Вы можете вернуть наблюдаемую угловую охрану.