2017-10-18 103 views
1

我最近被卡住角度的警衛。 CanActive只在加載頁面時運行一次,並且不在被保護的路由內的路由更改上運行。我認爲這已經改變了,因爲它用於每次更改。從我在論壇中閱讀的內容中,我應該使用CanActivateChild。事情是,我們的應用程序由幾個模塊組成,它們有幾個路由後代,當我在根模塊中使用CanActivateChild時,在更改路由時會多次調用它。角度:運行canActivate每個路線變化

我覺得爲每個孩子分配一個警衛是愚蠢的,因爲對於AppModule,這些懶惰的加載子模塊應該只是'黑盒子',我想要定義所有這些模塊應該被保護。

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' 
    } 
]; 

有沒有解決方法?或者你認爲這是安全方面的「不是問題」?

謝謝大家。

回答

0

面對同樣的問題,我在問題上找到的所有問題都很少有關於Github的封閉問題,Angular devs聲明這種行爲是「按設計」。

所以我最後做的是在app.component在導航事件訂閱和射擊AuthGuard檢查有:

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是相當標準:

@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; 
     }); 
    } 
    } 

和公共路線應配置像這樣:

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

這種實現的優點是每個東西被默認保護,公共路線應該明確配置,這將減少不保護某些路線的可能性。還會將此重構爲某種服務,以便能夠跨多個應用程序使用它。

this answer的啓發。

+0

是的,我發現很相似。 「按設計」。我發現你的答案是迄今爲止最好的解決方案,所以謝謝你! –