CRITICAL: クライアントサイドのガードをアクセス制御の唯一のソースとして決して信頼しないでください。Webブラウザで実行されるすべてのJavaScriptは、ブラウザを実行しているユーザーによって変更される可能性があります。クライアントサイドのガードに加えて、常にサーバーサイドでユーザー認証を強制してください。
ルートガードは、ユーザーが特定のルートに移動できるか、または特定のルートから離れることができるかを制御する関数です。それらは、ユーザーが特定のルートにアクセスできるかどうかを管理するチェックポイントのようなものです。ルートガードを使用する一般的な例には、認証とアクセス制御があります。
ルートガードの作成
Angular CLIを使用してルートガードを生成できます。
ng generate guard CUSTOM_NAME
これにより、使用するルートガードのタイプを選択するよう求められ、対応するCUSTOM_NAME-guard.tsファイルが作成されます。
TIP: Angularプロジェクトで個別のTypeScriptファイルを作成することで、手動でルートガードを作成できます。開発者は通常、他のファイルと区別するために、ファイル名に-guard.tsのサフィックスを追加します。
ルートガードの戻り値の型
すべてのルートガードは、同じ戻り値の型を共有します。これにより、ナビゲーションを制御する柔軟性が得られます。
| 戻り値の型 | 説明 |
|---|---|
boolean |
true はナビゲーションを許可し、 false はブロックします (CanMatch ルートガードに関する注記を参照) |
UrlTree or RedirectCommand |
ブロックする代わりに別のルートにリダイレクトします |
Promise<T> or Observable<T> |
ルーターは最初に発行された値を使用し、その後購読を解除します |
NOTE: CanMatch は異なる動作をします — false を返すと、Angularはナビゲーションを完全にブロックする代わりに、他のマッチするルートを試行します。
ルートガードの種類
Angularは、それぞれ異なる目的を持つ4種類のルートガードを提供します。
すべてのガードは、route引数を介してルートレベルで提供されるサービスおよびルート固有の情報にアクセスできます。
CanActivate
CanActivateガードは、ユーザーがルートにアクセスできるかどうかを決定します。これは、認証と認可に最も一般的に使用されます。
以下のデフォルト引数にアクセスできます。
route:ActivatedRouteSnapshot- アクティブ化されるルートに関する情報を含みますstate:RouterStateSnapshot- ルーターの現在の状態を含みます
標準のガード戻り値の型を返すことができます。
export const authGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
) => {
const authService = inject(AuthService);
return authService.isAuthenticated();
};
Tip: ユーザーをリダイレクトする必要がある場合は、URLTreeまたはRedirectCommandを返します。falseを返してから、プログラムでユーザーをnavigateしてはいけません。
詳細については、CanActivateFnのAPIドキュメントを参照してください。
CanActivateChild
CanActivateChildガードは、ユーザーが特定の親ルートの子ルートにアクセスできるかどうかを決定します。これは、ネストされたルートのセクション全体を保護したい場合に役立ちます。言い換えれば、canActivateChildは_すべて_の子に対して実行されます。子コンポーネントの下に別の子コンポーネントがある場合、canActivateChildは両方のコンポーネントに対して一度実行されます。
以下のデフォルト引数にアクセスできます。
childRoute:ActivatedRouteSnapshot- アクティブ化される子ルートの「将来の」スナップショット(つまり、ルーターがナビゲートしようとしている状態)に関する情報を含みますstate:RouterStateSnapshot- ルーターの現在の状態を含みます
標準のガード戻り値の型を返すことができます。
export const adminChildGuard: CanActivateChildFn = (
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
) => {
const authService = inject(AuthService);
return authService.hasRole('admin');
};
詳細については、CanActivateChildFnのAPIドキュメントを参照してください。
CanDeactivate
CanDeactivateガードは、ユーザーがルートを離れることができるかどうかを決定します。一般的なシナリオは、未保存のフォームからのナビゲーションを防ぐことです。
以下のデフォルト引数にアクセスできます。
component:T- 非アクティブ化されるコンポーネントインスタンスcurrentRoute:ActivatedRouteSnapshot- 現在のルートに関する情報を含みますcurrentState:RouterStateSnapshot- 現在のルーターの状態を含みますnextState:RouterStateSnapshot- ナビゲート先の次のルーターの状態を含みます
標準のガード戻り値の型を返すことができます。
export const unsavedChangesGuard: CanDeactivateFn<Form> = (
component: Form,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot,
) => {
return component.hasUnsavedChanges()
? confirm('You have unsaved changes. Are you sure you want to leave?')
: true;
};
詳細については、CanDeactivateFnのAPIドキュメントを参照してください。
CanMatch
CanMatchガードは、パスのマッチング中にルートがマッチング可能かどうかを決定します。他のガードとは異なり、拒否された場合でもナビゲーションを完全にブロックするのではなく、他のマッチングするルートを試行します。これは、機能フラグ、A/Bテスト、または条件付きルート読み込みに役立ちます。
以下のデフォルト引数にアクセスできます。
route:Route- 評価されているルート設定segments:UrlSegment[]- 以前の親ルート評価によって消費されていないURLセグメント
標準のガード戻り値の型を返すことができますが、falseを返した場合、Angularはナビゲーションを完全にブロックするのではなく、他のマッチングするルートを試行します。
export const featureToggleGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => {
const featureService = inject(FeatureService);
return featureService.isFeatureEnabled('newDashboard');
};
また、同じパスに対して異なるコンポーネントを使用できます。
// 📄 routes.ts
const routes: Routes = [
{
path: 'dashboard',
component: AdminDashboard,
canMatch: [adminGuard],
},
{
path: 'dashboard',
component: UserDashboard,
canMatch: [userGuard],
},
];
この例では、ユーザーが/dashboardにアクセスすると、正しいガードにマッチする最初のものが使用されます。
詳細については、CanMatchFnのAPIドキュメントを参照してください。
ルートへのガードの適用
ルートガードを作成したら、ルート定義でそれらを設定する必要があります。
ガードは、単一のルートに複数のガードを適用できるように、ルート設定で配列として指定されます。それらは配列に現れる順序で実行されます。
import {Routes} from '@angular/router';
import {authGuard} from './guards/auth.guard';
import {adminGuard} from './guards/admin.guard';
import {canDeactivateGuard} from './guards/can-deactivate.guard';
import {featureToggleGuard} from './guards/feature-toggle.guard';
const routes: Routes = [
// Basic CanActivate - 認証が必要
{
path: 'dashboard',
component: Dashboard,
canActivate: [authGuard],
},
// 複数のCanActivateガード - 認証と管理者ロールが必要
{
path: 'admin',
component: Admin,
canActivate: [authGuard, adminGuard],
},
// CanActivate + CanDeactivate - 未保存の変更チェック付き保護ルート
{
path: 'profile',
component: Profile,
canActivate: [authGuard],
canDeactivate: [canDeactivateGuard],
},
// CanActivateChild - すべての子ルートを保護
{
path: 'users', // /user - 保護されていない
canActivateChild: [authGuard],
children: [
// /users/list - 保護されている
{path: 'list', component: UserList},
// /users/detail/:id - 保護されている
{path: 'detail/:id', component: UserDetail},
],
},
// CanMatch - 機能フラグに基づいてルートを条件付きでマッチング
{
path: 'beta-feature',
component: BetaFeature,
canMatch: [featureToggleGuard],
},
// ベータ機能が無効な場合のフォールバックルート
{
path: 'beta-feature',
component: ComingSoon,
},
];