14

ピクルスが少しあります。CanActivateユーザーが特定のルートへのアクセスを許可されているかどうかを確認するために、ルート ガード (インターフェイスの実装) を使用しています。

const routes: Routes = [
    {
        path: '',
        component: DashboardViewComponent
    },
    {
        path: 'login',
        component: LoginViewComponent
    },
    {
        path: 'protected/foo',
        component: FooViewComponent,
        data: {allowAccessTo: ['Administrator']},
        canActivate: [RouteGuard]
    },
    {
        path: '**',
        component: ErrorNotFoundViewComponent
    }
];

これで、「/protected/foo」ルートがアクティブ化されるのを防ぐのにうまく機能しますが、アクセスしようとしているルートが禁止されていることをユーザーに伝えたいと思います (サーバーから取得する可能性のある 403 Forbidden に似ています)。

問題: ユーザーをエラー ルートにリダイレクトせずに、この特別なエラー ビューを表示するにはどうすればよいでしょうか。 そしてRouteGuard、禁止されたルートを実際にロードせずに my を使用するにはどうすればよいですか? my 内のアクセスをチェックしてFooViewComponent別のビューを表示するとRouteGuard、そもそも持っているポイントが無効になるからです。

RouteGuard理想的には、メソッドでfalse を返すだけでなくcanActivate()、コンポーネントを完全に say に置き換えたいと思いますErrorForbiddenViewComponent。しかし、それを行う方法がわかりません。または、イベントが可能ですか。代替案はありますか?

これは私のルートガードが今どのように見えるかです:

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

@Injectable()
export class RouteGuard implements CanActivate {

    constructor(
        private router: Router,
        private auth: AuthService
    ) {}

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        const { auth, router } = this;
        const { allowAccessTo } = next.data;
        const identity = auth.getIdentity();
        if (
            identity &&
            allowAccessTo.indexOf(identity.role)
        ) {
            // all good, proceed with activating route
            return true;
        }
        if (identity) {
            // TODO show ErrorForbiddenViewComponent instead of redirecting
            console.log('403 Forbidden >>', next);
        }
        else { 
            // not logged in: redirect to login page with the return url
            const [returnUrl, returnQueryParams] = state.url.split('?');
            console.log('401 Unauthorised >>', returnUrl, returnQueryParams, next);
            router.navigate(['/login'], {queryParams: {returnUrl, returnQueryParams}});
        }
        return false;
    }
}

したがって、ルートのロードを妨げているだけですが、リダイレクトはしていません。ログに記録されていない訪問者のみをログイン ルートにリダイレクトします。

理由:

  • ルートはアプリケーションの特定の状態を反映する必要があります - ルート URL にアクセスすると、その状態が再作成されます
  • エラー ルート (404 Not Found を除く) を持つことは、アプリケーションが実際にエラー状態を再現できることを意味します。なぜアプリケーションの状態としてエラー状態を保持するのでしょうか? デバッグの目的で、ログ (コンソールまたはサーバー) を使用する必要があります。エラー ページに再度アクセスすると (ページの更新など)、ログが妨げられる可能性があります。
  • また、エラー ルート アプリにリダイレクトすることで、ユーザーにエラーの洞察を提供する必要があります。さらに言えば、いくつかのパラメーターを url 経由で渡すか、(さらに悪いことに) エラー サービスでエラー状態を維持し、エラー ルートにアクセスするときにそれを取得する必要があります。
  • また、RouteGuard を無視してコンポーネントをロードし、その中のアクセスをチェックすると、(ユーザーが許可されていないため) とにかく使用されない余分な依存関係がロードされる可能性があり、遅延ロード全体がはるかに困難になります。

誰かがこれに対する何らかの解決策を持っていますか? また、Angular 2+ が長い間存在していた後、誰もこの種の状況を経験しなかったのはどうしてだろうか? 誰もがリダイレクトで大丈夫ですか?

また、私は現在FooViewComponent同期的に使用していますが、将来変更される可能性があることに注意してください!

4

4 に答える 4