角度:在每次更改路线时运行canActivate [英] Angular: Run canActivate on each route change

查看:67
本文介绍了角度:在每次更改路线时运行canActivate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在Angular路线守卫中陷入困境.当页面被加载时,CanActive仅运行一次,并且不会在受保护的路由内的路由更改上运行.我认为这已更改,因为它曾经在每次更改时运行.从我在论坛上阅读的内容来看,我应该使用CanActivateChild.事实是,我们的应用程序由几个模块组成,这些模块具有多个路由后代,当我在根模块中使用CanActivateChild时,更改路由时会多次调用它.

我发现为每个孩子分配一个防护很愚蠢,因为对于AppModule来说,那些延迟加载的子模块应该只是黑匣子",我想定义所有这些模块都应该受到保护.

 导出const路由:Routes = [{路径:"404",组件:NotFoundComponent},{小路: '',canActivate:[AuthGuard],组件:FullLayoutComponent,数据: {标题:首页"},孩子们: [{路径:管理",loadChildren:"./administration/administration.module#AdministrationModule"},{路径:设置",loadChildren:"./settings/settings.module#SettingsModule"}]},{小路: '',loadChildren:"./account/account.module#AccountModule"},{小路: '**',redirectTo:'404'}]; 

对此有什么解决办法吗?还是您认为这与安全性无关紧要?

谢谢大家.

解决方案

面对相同的问题,我发现的所有问题都是在Github上很少有Angular devs声明为是设计使然"的封闭问题./p>

所以我最终要做的是订阅app.component中的导航事件并触发AuthGuard检查:

 构造函数(专用路由器:路由器,专用路由:ActivatedRoute,私人AuthGuard:AuthGuard,){}ngOnInit(){this.router.events.subscribe(event => {if(RoutesRecognized的事件instance){this.guardRoute(event);}}));}私人guardRoute(事件:RoutesRecognized):无效{如果(this.isPublic(event)){返回;}如果(!this.callCanActivate(event,this.authGuard)){返回;}}私人通话:CanActivate(事件:RoutesRecognized,后卫:CanActivate){返回guard.canActivate(this.route.snapshot,event.state);}私人isPublic(事件:RoutesRecognized){返回event.state.root.firstChild.data.isPublic;} 

AuthGuard非常标准:

  @Injectable()导出类AuthGuard实现CanActivate {构造函数(私有auth:AuthService,私有路由器:Router){}canActivate():Promise< boolean>{返回this.auth.isLoggedInPromise().then(isLoggedIn => {如果(!isLoggedIn){this.router.navigate(["/login"]);}返回isLoggedIn;});}} 

公共路线应配置如下:

  {路径:登录",组件:LoginComponent,数据:{isPublic:正确}} 

这种实现的优点是,默认情况下所有内容都受保护,并且应该显式配置公用路由,这将减少使某些路由不受保护的可能性.还将其重构为某种服务,以便能够在多个应用程序中使用它.

此答案的启发.

I got stuck recently with Angular route guards. CanActive runs only once when the page is loaded and does not run on route change within the guarded route. I think this was changed because it used to run on each change. From what I read in forums, I should use CanActivateChild. The thing is, our application consists of several modules, that have several route descendants and when I use CanActivateChild in root module, it is called several times when changing the route.

I find it dumb to assign a guard to each child because, for AppModule, those lazy loaded child modules should be just 'Black Boxes' and I wanted to define that all those modules should be guarded.

export const routes: Routes = [
  {
    path: '404',
    component: NotFoundComponent
  },
  {
    path: '',
    canActivate: [AuthGuard],
    component: FullLayoutComponent,
    data: {
      title: 'Home'
    },
    children: [
      {
        path: 'administration',
        loadChildren: './administration/administration.module#AdministrationModule'
      },
      {
        path: 'settings',
        loadChildren: './settings/settings.module#SettingsModule'
      }
    ]
  },
  {
    path: '',
    loadChildren: './account/account.module#AccountModule'
  },
  {
    path: '**',
    redirectTo: '404'
  }
];

Is there any solution to this? Or do You find this as 'not an issue' regarding security?

Thank You all.

解决方案

Faced the same issue and all I was able to find on issue are few closed issues on Github with Angular devs statements that such behavior "is by design".

So what I ended up doing is subscribing on navigation events in app.component and firing AuthGuard check there:

constructor(
  private router: Router,
  private route: ActivatedRoute,
  private authGuard: AuthGuard,
) {}

ngOnInit() {
  this.router.events
    .subscribe(event => {
      if (event instanceof RoutesRecognized) {
        this.guardRoute(event);
      }
    }));
}

private guardRoute(event: RoutesRecognized): void {
  if (this.isPublic(event)) {
    return;
  }

  if (!this.callCanActivate(event, this.authGuard)) {
    return;
  }
}

private callCanActivate(event: RoutesRecognized, guard: CanActivate) {
  return guard.canActivate(this.route.snapshot, event.state);
}

private isPublic(event: RoutesRecognized) {
  return event.state.root.firstChild.data.isPublic;
}

AuthGuard is rather standard:

@Injectable()
export class AuthGuard implements CanActivate{

  constructor(private auth: AuthService, private router: Router) { }

  canActivate(): Promise<boolean> {
    return this.auth.isLoggedInPromise()
      .then(isLoggedIn => {
        if (!isLoggedIn) {
          this.router.navigate(["/login"]);
        }
        return isLoggedIn;
      });
    }
  }

And public routes should be configured like this:

{
  path: "login",
  component: LoginComponent,
  data: { isPublic: true }
}

The plus of such implementation is that everything is protected by default and public route should be configured explicitly, which will reduce the possibility of leaving some routes unprotected. Will also refactor this into some kind of service, to be able to use it across multiple apps.

Inspired by this answer.

这篇关于角度:在每次更改路线时运行canActivate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆