TypeScript と Angular Routing で canActivate ガードをマスター:完全ガイド
Angular ですべてのルートに canActivate ガードを適用する方法
アプリレベルのガードを使用する
アプリレベルのガードは、ルーター設定で定義されます。このガードは、すべてのルートに適用され、すべてのルートにアクセスする前にチェックされます。
import { CanActivate, Router } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): boolean {
if (!this.authService.isLoggedIn()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
このコードでは、AuthGuard
という名前のガードを作成しています。このガードは、canActivate
メソッドを実装しており、ユーザーがログインしているかどうかをチェックします。ユーザーがログインしていない場合は、ログインページにリダイレクトされます。
このガードをアプリレベルで適用するには、ルーター設定で次のように指定します。
{
path: '',
canActivate: [AuthGuard],
children: [
{
path: 'home',
component: HomeComponent
},
{
path: 'about',
component: AboutComponent
}
]
}
この設定により、AuthGuard
は /
パスとすべての子ルートに適用されます。
ルートごとにガードを使用する
ルートごとにガードを使用するには、各ルートの canActivate
プロパティにガードを指定します。
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'about',
component: AboutComponent,
canActivate: [AuthGuard]
}
この設定により、AuthGuard
は home
と about
ルートにのみ適用されます。
マルチガードを使用する
複数のガードを適用するには、canActivate
プロパティに配列として指定します。
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard, AdminGuard]
}
この設定により、home
ルートにアクセスするには、ユーザーが AuthGuard
と AdminGuard
の両方のガードに合格する必要があります。
注
canActivate
ガードは、ナビゲーションイベントをキャンセルできます。ナビゲーションイベントをキャンセルするには、false
を返す必要があります。canActivate
ガードは、非同期処理を実行できます。非同期処理を実行する場合は、Observable
またはPromise
を返す必要があります。
アプリレベルのガード
// auth.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class AuthService {
isLoggedIn(): boolean {
// ログイン状態のチェックロジック
}
}
// auth.guard.ts
import { CanActivate, Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(): boolean {
if (!this.authService.isLoggedIn()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: '',
canActivate: [AuthGuard],
children: [
{
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
},
{
path: 'about',
loadChildren: () => import('./about/about.module').then(m => m.AboutModule)
}
]
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
ルートごとのガード
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { AdminGuard } from './admin.guard';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'about',
component: AboutComponent,
canActivate: [AuthGuard]
},
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard, AdminGuard]
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
マルチガード
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { AdminGuard } from './admin.guard';
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard, AdminGuard]
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
- 上記のコードはあくまで一例です。実際には、アプリケーションのニーズに合わせて調整する必要があります。
カスタムルーターモジュールを作成して、すべてのルートにガードを適用することができます。この方法は、より柔軟な制御と、コードの再利用性を高めることができます。
// custom-router.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: '',
canActivate: [AuthGuard],
children: [
{
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
},
{
path: 'about',
loadChildren: () => import('./about/about.module').then(m => m.AboutModule)
}
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomRouterModule {}
このコードでは、CustomRouterModule
という名前のカスタムルーターモジュールを作成しています。このモジュールは、AuthGuard
をすべてのルートに適用するルート設定を定義しています。
カスタムルーターモジュールを使用するには、アプリモジュールのインポートステートメントに追加する必要があります。
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CustomRouterModule } from './custom-router.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
CustomRouterModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
グローバルルートガードを使用する
グローバルルートガードは、Angular 9 以降で使用できる新しい機能です。この機能を使用すると、アプリレベルでルートガードを定義できます。
// app.routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{
path: '',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
},
{
path: 'about',
loadChildren: () => import('./about/about.module').then(m => m.AboutModule)
}
];
@NgModule({
imports: [RouterModule.forRoot(routes, {
preloadingStrategy: PreloadingStrategy.NoPreloading,
initialNavigation: createEmptyNavigation
})],
exports: [RouterModule]
})
export class AppRoutingModule {}
このコードでは、AuthGuard
をグローバルルートガードとして設定しています。これにより、AuthGuard
はすべてのルートに適用されます。
ルーターイベントリスナーを使用する
ルーターイベントリスナーを使用して、ルート変更を検出し、それに応じてガードを実行できます。
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard {
constructor(private router: Router, private authService: AuthService) {}
canActivate(): boolean {
if (!this.authService.isLoggedIn()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
ngOnInit() {
this.router.events.subscribe((event: RouterEvent) => {
if (event instanceof NavigationStart) {
if (!this.authService.isLoggedIn()) {
this.router.navigate(['/login']);
}
}
});
}
}
angular typescript angular-routing