2016-02-12 82 views
8

我有一個角度2應用程序,我需要在每個頁面上進行認證。所以我已經實現了一個自定義的RouterOutlet來確認我在每次頁面更改時都登錄了。Angular 2兒童路由認證

@Directive({ 
    selector: 'auth-outlet' 
}) 
export class AuthOutlet extends RouterOutlet { 
    publicRoutes: any; 
    private parentRouter: Router; 
    private authService: AuthService; 
    constructor(_elementRef: ElementRef, 
       _loader: DynamicComponentLoader, 
       _parentRouter: Router, 
       @Attribute('name') nameAttr: string, 
       _authService: AuthService) { 

     super(_elementRef, _loader, _parentRouter, nameAttr); 
     this.parentRouter = _parentRouter; 
     this.authService = _authService; 
     this.publicRoutes = { 
      'Login': true 
     }; 
    } 

    activate(oldInstruction: ComponentInstruction) { 
     var url = this.parentRouter.lastNavigationAttempt; 
     console.log('attemping to nav'); 
     if (!this.publicRoutes[url] && !this.authService.loggedIn){ 
      var newInstruction = new ComponentInstruction('Login', [], new RouteData(), Login, false, 1); 
      return super.activate(newInstruction); 
     } else { 
      return super.activate(oldInstruction); 
     } 
    } 
} 

這裏是一個工作代碼: http://plnkr.co/edit/YnQv7Mh9Lxc0l0dgAo7B?p=preview

有沒有更好的辦法攔截路線的變化和重定向登錄時,用戶沒有通過驗證?

+1

棒極了!你還需要什麼! – micronyks

+0

那麼,有一件事你不應該新建一個ComponentInstruction。所以這已經有問題了。此外,如果您處於不瞭解登錄路線的兒童路線中,則會出現問題。 (我在海報上處理過這個問題) –

+0

如果有人深入鏈接到頁面,那麼服務器就會參與進來,並且你在服務器上進行認證檢查。如果有人被授​​權,他們會進入您的應用程序。一旦進入你的應用程序,他們可以自由移動。瀏覽器和js不應該在這裏進行身份驗證檢查,服務器應該這樣做。 –

回答

8

對於任何發現這一點的人來說,現在Angular 2的答案是使用「Guards」作爲新路由器的一部分。見角2文檔:

https://angular.io/docs/ts/latest/guide/router.html#!#guards

一個基本的後衛只是實現了「CanActivate」,並且可以工作如下:

import {Injectable} from "@angular/core"; 
import {CanActivate, Router} from "@angular/router"; 
import {AuthService} from "../services/auth.service"; 

@Injectable() 
export class AuthGuard implements CanActivate { 
    constructor(private authService:AuthService, private router:Router){} 

    canActivate(){ 
     if(this.authService.isAuthenticated()) 
      return true; 

     this.router.navigate(["/login"]); 
     return false; 
    } 
} 

正如你可以看到在這個例子我有一個AuthService運行別的地方(實現並不重要),它可以告訴警衛用戶是否已被認證。如果他們有,返回true,導航像往常一樣發生。如果他們沒有,我們將返回false並將其重定向到登錄屏幕。

+0

嗨,John,歡迎來到SO,謝謝你的回答。只有代碼的答案是不鼓勵的,因爲鏈接可能會隨着時間的推移而變化並且變得無效 - 因此,提供完整的答案可以站在這裏,以鏈接作爲參考,這會更好。你是否介意以此來編輯你的答案?再次感謝! –

+0

@JohnAckerman但是與OP相比,這種方法的缺點是我們不得不爲所有auth所需的路徑提供這個守衛,所以複製和使用OP的代碼我們也可以存儲最後一次嘗試的路由,然後在用戶登錄後用於重定向用戶是成功的。 – lbrahim

+0

@Ibrahim不是真的。如果你有一個需要在守衛後面的整個部分(模塊?),那麼你應該相應地構建你的路線。你只需要家長級別的警衛。如果您爲子項定義了/ admin路由,則唯一的管理路由需要守衛,並且子項會繼承它。 –

2

下面是使用AuthGuard和Angular 2 RC6的更新示例。

路線與家庭路線由AuthGuard保護

import { Routes, RouterModule } from '@angular/router'; 

import { LoginComponent } from './login/index'; 
import { HomeComponent } from './home/index'; 
import { AuthGuard } from './_guards/index'; 

const appRoutes: Routes = [ 
    { path: 'login', component: LoginComponent }, 

    // home route protected by auth guard 
    { path: '', component: HomeComponent, canActivate: [AuthGuard] }, 

    // otherwise redirect to home 
    { path: '**', redirectTo: '' } 
]; 

export const routing = RouterModule.forRoot(appRoutes); 

AuthGuard重定向如果用戶沒有

import { Injectable } from '@angular/core'; 
import { Router, CanActivate } from '@angular/router'; 

@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private router: Router) { } 

    canActivate() { 
     if (localStorage.getItem('currentUser')) { 
      // logged in so return true 
      return true; 
     } 

     // not logged in so redirect to login page 
     this.router.navigate(['/login']); 
     return false; 
    } 
} 

記錄對於完整的例子和工作演示,你可以到登錄頁面退房this post