Angular 2 - ルーティング:CanActivateをマスターして、より強力なアプリケーションを構築しよう!
Angular 2 - ルーティング - CanActivate の Observable を使った動作解説
CanActivate
ガードは、boolean
値または Observable<boolean>
を返す関数として実装できます。boolean
値を返す場合、true
はルートへのアクセスを許可し、false
はアクセスを拒否します。
Observable<boolean>
を返す場合、ガードは、ルートへのアクセスを許可または拒否する前に、非同期操作を実行できます。これは、API 呼び出しを使用してユーザーの認証状態を確認したり、ローカル ストレージからアクセス許可を取得したりするような場合に役立ちます。
Observable を使った CanActivate の動作
- ルーターがルートへのアクセスを試みます。
CanActivate
ガードが呼び出されます。- ガードは、非同期操作を実行するために
Observable<boolean>
を返します。 - Observable が完了すると、ガードは
true
またはfalse
の値を返します。 - ルーターは、ガードの値に基づいてルートへのアクセスを許可または拒否します。
例
次の例は、ユーザーが認証されているかどうかを確認するために Observable<boolean>
を使用する CanActivate
ガードを示しています。
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(): Observable<boolean> {
return this.authService.isAuthenticated().pipe(
map(authenticated => {
if (!authenticated) {
this.router.navigate(['/login']);
return false;
}
return true;
})
);
}
}
この例では、AuthGuard
クラスは CanActivate
インターフェースを実装しています。canActivate
メソッドは、Observable<boolean>
を返します。
canActivate
メソッドは、authService
サービスの isAuthenticated
メソッドを呼び出して、ユーザーが認証されているかどうかを確認します。isAuthenticated
メソッドは、boolean
値を返す Observable
を返します。
Observable
が完了すると、map
オペレーターを使用して、true
または false
の値を返します。ユーザーが認証されていない場合、router
サービスを使用して /login
ルートにナビゲートします。
CanActivate
ガードは、ナビゲーションイベントをキャンセルするために使用することもできます。- 複数の
CanActivate
ガードをチェーンして、より複雑なアクセス制御ロジックを実装できます。 CanActivate
ガードは、ルートレベルとコンポーネントレベルの両方で使用できます。
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(): Observable<boolean> {
return this.authService.isAuthenticated().pipe(
map(authenticated => {
if (!authenticated) {
this.router.navigate(['/login']);
return false;
}
return true;
})
);
}
}
例:API 呼び出しを使用してアクセス許可を確認する CanActivate ガード
この例では、CanActivate
ガードを使用して、API 呼び出しを使用してユーザーのアクセス許可を確認します。ユーザーにアクセス許可がない場合、/forbidden
ルートにリダイレクトします。
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { PermissionService } from './permission.service';
@Injectable()
export class PermissionGuard implements CanActivate {
constructor(private router: Router, private permissionService: PermissionService) {}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
const requiredPermission = route.data['requiredPermission'];
return this.permissionService.hasPermission(requiredPermission).pipe(
map(hasPermission => {
if (!hasPermission) {
this.router.navigate(['/forbidden']);
return false;
}
return true;
})
);
}
}
説明
- コードは TypeScript で記述されていますが、JavaScript でも同様のロジックを実装できます。
- Angular 2 と RxJS に関する詳細は、公式ドキュメントを参照してください。
Promise を使用する
CanActivate
ガードは、Promise<boolean>
を返す関数としても実装できます。これは、非同期操作を実行する必要がある場合に役立ちます。
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(): Promise<boolean> {
return this.authService.isAuthenticated().then(authenticated => {
if (!authenticated) {
this.router.navigate(['/login']);
return false;
}
return true;
});
}
}
RouterEvent を使用する
CanActivate
ガードは、RouterEvent
を返す関数としても実装できます。これは、ナビゲーションイベントをキャンセルするために使用できます。
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): RouterEvent | boolean {
if (!this.authService.isAuthenticated()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
カスタム CanActivate クラスを作成する
独自のロジックを備えた CanActivate
ガードを実装する必要がある場合は、カスタムクラスを作成できます。
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
@Injectable()
export class CustomAuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
// カスタムロジックを実装する
if (// 条件が満たされない場合) {
this.router.navigate(['/forbidden']);
return false;
}
return true;
}
}
angular angular2-routing angular2-http