2016-02-12 9 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

これを見つけた人には、角度2の答えは、新しいルータの一部として「ガード」を使用することです。基本的なガードは、単に「CanActivate」を実装し、次のように仕事ができる

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

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を持って角度2のマニュアルを参照してください。 (実装は重要ではありません)、ユーザが認証されたかどうかをガードに伝えることができます。持っている場合はtrueを返し、ナビゲーションはいつものように行われます。そうでない場合は、falseを返してログイン画面にリダイレクトします。

+0

こんにちはJohn、ようこそ、あなたの答えに感謝します。リンクは時間とともに変化し、無効になる可能性があるため、コードのみの回答は推奨されません。したがって、リンクを参考にしてここに単独で記入することをお勧めします。あなたはこれを覚えてあなたの答えを編集してもよろしいですか?再度、感謝します! –

+0

@JohnAckermanしかし、OPの方法と比較したこのアプローチの欠点は、すべての認証に必要なすべてのパスに対してこのガードについて言及する必要があることです.OPコードを複製して使用すると、最後に試行されたルートを保存し、成功です。 – lbrahim

+0

@イブラヒムは本当にありません。ガードの背後にある必要があるサイトの全セクション(モジュール?)がある場合は、それに応じてルートを構造化する必要があります。親レベルでのみガードが必要です。子と一緒に/ adminルートを定義すると、管理ルートだけがガードを必要とし、子がそれを継承します。 –

0

CanActivateも使用できますが、現時点では直接DIはサポートされていません。ここに素敵なworkaround thoがあります。

幸運。

2

ここでは、AuthGuardとAngular 2 RC6を使用した更新例を示します。

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 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

関連する問題