我可以使用防火墙登录,但在我的应用程序中,我有3个级别的用户。我们叫他们管理员,用户,编辑。我在Firebase提供的自定义声明中保留用户的角色。
在AuthGuard中,我传递数据expectedRoles = ['admin', 'editor']
,添加希望允许特定路由的角色。并且我想重定向到自己的页面,比如尝试管理路径的编辑器将返回到编辑器仪表板。
这是我的AuthGuard的canActivate
函数:
return this.auth.user.pipe(
map(user => {
if (user) {
user.getIdTokenResult().then((idTokenResult) => {
if (idTokenResult.claims.admin) {
if (expectedRoles.indexOf('admin') > -1) {
return true;
} else {
// return back to admin dashboard
this.router.navigate(['/admin']);
}
} else if (idTokenResult.claims.editor) {
if (expectedRoles.indexOf('editor') > -1) {
return true;
} else {
// return back to editor dashboard
this.router.navigate(['/editor']);
}
} else if (idTokenResult.claims.user) {
if (expectedRoles.indexOf('user') > -1) {
return true;
} else {
// return back to user dashboard
this.router.navigate(['/user']);
}
} else {
// Unexpected claim, better logout, TODO; display something
this.router.navigate(['/auth/logout']);
}
});
} else {
// User is not authenticated
// Check if we are expecting a guest
if (expectedRoles.indexOf('guest') > -1) {
return true;
} else {
this.router.navigate(['/auth/login']);
}
}
})
).first();
在添加user.getIdTokenResult().then(...)
之前,它运行得很好,我知道这可能是因为没有等待异步调用来解析自定义声明。我怎么才能解决这个问题?
发布于 2019-03-22 15:56:46
使用switchMap
代替地图,生成函数async
并等待结果。switchMap
接受async
函数返回的承诺。然后在内部您可以使用await
。
return this.auth.user.pipe(
// switchMap instead of map
// async function call
switchMap(async (user) => {
if (user) {
// await here
await user.getIdTokenResult().then((idTokenResult) => {
if (idTokenResult.claims.admin) {
if (expectedRoles.indexOf('admin') > -1) {
return true;
} else {
// return back to admin dashboard
this.router.navigate(['/admin']);
}
} else if (idTokenResult.claims.editor) {
if (expectedRoles.indexOf('editor') > -1) {
return true;
} else {
// return back to editor dashboard
this.router.navigate(['/editor']);
}
} else if (idTokenResult.claims.user) {
if (expectedRoles.indexOf('user') > -1) {
return true;
} else {
// return back to user dashboard
this.router.navigate(['/user']);
}
} else {
// Unexpected claim, better logout, TODO; display something
this.router.navigate(['/auth/logout']);
}
});
} else {
// User is not authenticated
// Check if we are expecting a guest
if (expectedRoles.indexOf('guest') > -1) {
return true;
} else {
this.router.navigate(['/auth/login']);
}
}
})
).first();
这只是一个与此解决方案无关的提示--比在AuthGuard函数中加载令牌声明更好,您应该在用户登录后加载它,并以从登录响应存储信息的方式将其存储在存储中。这样会快得多。
发布于 2019-03-22 15:58:45
尝试使用rxjs管道进行内部可观察的调用: flatMap和flatMapTo或mergeMap或mergeMapTo。在您的具体案例中,我认为mergeMap是最好的选择。
请随意阅读rxjs中的那些管道,它们可能是解决方案。
https://stackoverflow.com/questions/55303417
复制相似问题