我如何在Angular中显示未经授权访问的错误页面?
我正在一个角度应用程序中使用authz。我们大量使用路由,所以在路由守卫中检查授权似乎是有意义的 我是通过我如何在Angular中显示未经授权访问的错误页面?,angular,typescript,authorization,Angular,Typescript,Authorization,我正在一个角度应用程序中使用authz。我们大量使用路由,所以在路由守卫中检查授权似乎是有意义的 我是通过canActivateChild路径来实现的,设置大致如下: class MyGuard implements CanActivateChild { canActivateChild(route, state) { return !route.data || route.data.active; } } const routes: Routes = [ {
canActivateChild
路径来实现的,设置大致如下:
class MyGuard implements CanActivateChild {
canActivateChild(route, state) {
return !route.data || route.data.active;
}
}
const routes: Routes = [
{
path: '',
canActivate: [MyGuard],
canActivateChild: [MyGuard],
children: [
{
path: 'hello', component: HelloComponent, data: { active: false }
}
]
}
]
class MyGuard implements CanActivateChild {
canActivateChild(route, state): boolean | Observable<boolean> {
if (!route.data || route.data.active) {
// TODO: return your modal observable here and map it to boolean, e.g. via:
return modalService.alert('Data error').map(() => false);
}
return true;
}
}
(这显然大大简化了,但我认为如何确定路线是否得到授权的细节并不相关。一个更完整的工作示例是StackBlitz上的)
我的问题是,当授权失败时,route guard只允许我做两件事:返回false
,让导航完全取消并保持在原始路线上;或者重定向到其他URL
我想要的UI显示了一条错误消息,但在用户试图导航到的URL下。(即,如果设置权限时出现错误,用户更容易报告“嘿,我无法访问此URL”,然后重新加载页面。)实际上,我希望服务器返回HTTP 403状态和正文
我考虑过不在路线上进行检查,让目标组件本身显示其他内容。我不是特别喜欢这个,如果没有其他原因的话,它会干扰模块的按需加载。有没有一种“干净”的方法可以从路由器上做到这一点?我知道这不是您等待的响应,但我质疑其原理。Angular中的路由确保一个重要的不变量始终为真:路由中使用的组件通过路由表给出。这就是为什么你没有找到一个简单的方法来完成你的计划 我的猜测是,偏离这一原则就是要求在今后的道路上出现可维护性和/或可靠性问题 我将以下内容视为您最初愿望的解决方案:将失败的请求路由到
的/initial/path/failed
,此路由的组件包含可能对IT团队有用的错误数据
然后,在的/initial/path/failed
路由中,您设置了一个反向保护:如果权限正常,则重定向到的/initial/path
这样,就不会破坏路由宇宙核心的角度不变量
这一过程类似于未登录时回滚到登录页面,如果已登录则跳过登录页面
编辑:
我在评论中看到了你的观点,我基本上同意你的观点。
不过,为了尝试推进解决方案,这里有一个可接受的非样板近似:
创建一个简单的“失败”组件。它显示从服务获取的消息(典型的组件间消息传递,类似于flash消息功能)。谨防:
router.navigate(...).then(_ =>
Service.post_flash_message('instructions with "retry" link to initial url'));
这不完全是你的要求,而是迈向目标的一步。再加上一个想法:你是否考虑过在守卫中返回一个新的可观察目标?角度防护装置可以返回
布尔值
,也可以返回可观察值
。这样,在拒绝路由导航之前,您可以通过显示带有错误/警告消息的模式来延迟实际路由过程
这可以通过以下方式实现:
class MyGuard implements CanActivateChild {
canActivateChild(route, state) {
return !route.data || route.data.active;
}
}
const routes: Routes = [
{
path: '',
canActivate: [MyGuard],
canActivateChild: [MyGuard],
children: [
{
path: 'hello', component: HelloComponent, data: { active: false }
}
]
}
]
class MyGuard implements CanActivateChild {
canActivateChild(route, state): boolean | Observable<boolean> {
if (!route.data || route.data.active) {
// TODO: return your modal observable here and map it to boolean, e.g. via:
return modalService.alert('Data error').map(() => false);
}
return true;
}
}
MyGuard类实现了CanActivateChild{
canActivateChild(路由、状态):布尔值|可观察{
如果(!route.data | | route.data.active){
//TODO:在此处返回模态可观测值并将其映射为布尔值,例如通过:
返回modalService.alert('Data error').map(()=>false);
}
返回true;
}
}
实际上,我在我的应用程序中使用了这个模式,允许用户在模式中更新他们的令牌/登录(如果警卫检测到令牌过期,这很可能会导致服务器API错误),然后在获取新令牌后继续导航。防护装置将“悬挂”,直到可观察物发出
true
或false
这确实不是我想要的答案。我正在为用户而不是框架作者构建应用程序。我需要一个比含糊其辞的“这可能会导致问题”更强烈的警告——你写的每一行代码都可能。据我所知,Ng路由不允许像**/failed
这样的路由,因此您的方法似乎需要大量的样板文件,这很难成为维护的福音。我还认为所谓的与用户登录相似之处并不十分合适。未经身份验证的用户可能会采取措施纠正该问题-登录-这就是为什么他们会绕道登录页面并返回。对于未经授权的用户,他们可能不会采取任何行动,他们可能正在访问不应该访问的资源,或者管理员必须授予他访问权限;他们从一开始就处于死胡同,所以增加更多的步骤是没有意义的。如果有帮助的话,用一个额外的想法编辑我的答案。虽然我不太同意这个框架。当你选择一个有观点的框架时,你要么按规则行事,要么就开辟了一些困难的道路。这不是事实,而是经验,我同意这不是100%有效的。但我发现,当我陷入这种状态时,框架中通常有一个可接受的解决方案。你可以确定从A到B只能向后行驶,但这将是一个地狱般的旅程:)如果用户只是冷导航到一个未经授权的URL,比如在一个新选项卡中打开一个链接,这会做什么?我们确实有一个toast通知实用程序,但我真的不知道Ng是否会呈现任何内容。稍后我将保留这个技巧,但我必须强调这是授权,而不是身份验证。用户在应用程序UI中无需执行任何操作即可访问资源,如果他应该拥有资源,则管理员必须授予他相应的角色,并且用户必须硬加载才能加载新功能。