ピクルスが少しあります。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
同期的に使用していますが、将来変更される可能性があることに注意してください!