AngularJS路由$routeChangeSuccess未广播,需实现路由权限校验与403跳转
AngularJS ngComponentRouter 权限校验与重定向方案
哦,我懂你的问题了——你肯定是把旧的ngRoute模块的事件和ngComponentRouter搞混了!$routeChangeSuccess是ngRoute专属的广播事件,而你用的是AngularJS 1.5+推出的组件路由(ngComponentRouter),这俩根本不是一套东西,所以你监听不到这个事件太正常了😅。
下面给你两种适合ngComponentRouter的权限校验方案,都是官方推荐的方式:
方案一:组件内用$routerOnActivate钩子(推荐)
组件路由的设计就是和组件生命周期深度绑定的,每个路由对应的组件都可以实现$routerOnActivate钩子,这个钩子会在路由激活之前触发,正好用来做权限校验:
angular.module('yourApp').component('protectedDashboard', { template: '<h2>仅授权用户可见的仪表盘</h2>', controller: function($router, AuthService) { // 路由激活前的钩子 this.$routerOnActivate = function(nextRoute, prevRoute) { // 这里替换成你的权限校验逻辑,比如检查用户角色、路由权限 const hasAccess = AuthService.checkUserAccess(nextRoute.routeConfig.path); if (!hasAccess) { // 重定向到403页面(假设你的403路由名称是Forbidden) $router.navigate(['Forbidden']); } }; } });
nextRoute参数里包含了目标路由的所有配置信息,比如nextRoute.routeName、nextRoute.routeConfig,可以用来精准判断权限。- 这个方案适合需要针对单个组件做个性化权限校验的场景。
方案二:全局路由resolve拦截(统一处理)
如果想给所有路由统一加权限校验,不用每个组件都写钩子,可以在路由配置时用resolve属性,它会在路由加载前执行:
angular.module('yourApp').config(function($routerProvider, $q) { $routerProvider // 受保护的路由 .when('/dashboard', { component: 'protectedDashboard', resolve: { // 这里的resolve依赖会在路由激活前执行 authCheck: function($router, AuthService) { // 排除不需要校验的路由(比如登录页、403页) if (AuthService.isGuest()) { $router.navigate(['Forbidden']); // 返回rejected的Promise,阻止路由继续加载 return $q.reject('无访问权限'); } return true; } } }) // 403页面路由 .when('/forbidden', { component: 'forbiddenPage' }); });
- 如果resolve里的函数返回rejected的Promise,路由会被取消,同时我们可以在里面完成重定向。
- 要是想给所有路由批量加这个校验,可以封装一个通用的resolve函数,避免重复代码。
方案三:全局父组件统一拦截(更简洁)
创建一个根组件作为所有路由的父容器,在这个父组件的$routerOnActivate里做全局权限校验,所有子路由都会继承这个逻辑:
angular.module('yourApp').component('appRoot', { template: '<ng-outlet></ng-outlet>', // 子路由的渲染出口 controller: function($router, AuthService) { this.$routerOnActivate = function(nextRoute) { // 定义不需要校验的路由白名单 const whitelist = ['Login', 'Forbidden', 'Home']; if (!whitelist.includes(nextRoute.routeName) && !AuthService.hasAccess(nextRoute.routeName)) { $router.navigate(['Forbidden']); } }; } });
然后把根路由指向这个组件:
$routerProvider.root({ component: 'appRoot' });
这个方案最适合全局统一权限规则的场景,一次配置全路由生效。
最后再提醒一句:ngComponentRouter和ngRoute是完全独立的实现,千万不要混用它们的API哦!
内容的提问来源于stack exchange,提问作者Renaud is Not Bill Gates
相关产品推荐
相关产品推荐

