canActivate
のAngularドキュメント から、canActivate
ガードのみを使用してルートに進むことができるように見える場合、canActivate
関数は最終的にtrue
を返します。
「canActivate
クラスがfalse
と評価された場合にのみこのルートに進む」という言い方はありますか?
たとえば、ログインしているユーザーがログインページにアクセスできないようにするために、これを試してみましたが、うまくいきませんでした。
export const routes: Route[] = [
{ path: 'log-in', component: LoginComponent, canActivate: [ !UserLoggedInGuard ] },
コンソールでこのエラーが発生しました:
ERROR Error: Uncaught (in promise): Error: StaticInjectorError[false]:
StaticInjectorError[false]:
NullInjectorError: No provider for false!
Error: StaticInjectorError[false]:
StaticInjectorError[false]:
NullInjectorError: No provider for false!
あなたの質問で興味深いのは定式化です:
「canActivateクラスがfalseと評価された場合にのみこのルートに進むと言う方法はありますか?
そして、「直感的な」ソリューションをどのように表現したか:
{ path: 'log-in', component: LoginComponent, canActivate: [ !UserLoggedInGuard ] },
基本的に言って、あなたはnegate
の結果をUserLoggedInGuard@canActivate
UserLoggedInGuard
の次の実装について考えてみましょう。
@Injectable()
export class UserLoggedInGuard implements CanActivate {
constructor(private _authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this._authService.isLoggedIn();
}
}
次に、@ Mikeによって提案されたソリューションを見てみましょう
@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {
constructor(private _authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return !this._authService.isLoggedIn();
}
}
現在、このアプローチは問題ありませんが、UserLoggedInGuard
の(内部)実装と密接に結びついています。何らかの理由でUserLoggedInGuard@canActivate
変更、NegateUserLoggedInGuard
は壊れます。
どうすればそれを回避できますか?単純な乱用依存性注入:
@Injectable()
export class NegateUserLoggedInGuard implements CanActivate {
constructor(private _userLoggedInGuard: UserLoggedInGuard) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return !this._userLoggedInGuard.canActivate(route,state);
}
}
今これはやっています正確にあなたが表現したもの
canActivate: [ !UserLoggedInGuard ]
そして最良の部分:
UserLoggedInGuard
の内部実装と密に結合されていませんGuard
クラスの結果を操作するために展開できます問題について考えると、1つの解決策は、論理を逆に行うルートガードを実装することです。
import { MyService } from "./myservice.service";
import { CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router";
import { Injectable } from "@angular/core";
@Injectable()
export class MyGuard implements CanActivate {
constructor(private myService: MyService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.myService.isNotLoggedIn(); //if user not logged in this is true
}
}
同様の問題がありました。認証されていない場合にのみアクセス可能なログインページを作成し、認証されている場合にのみダッシュボードにアクセスできるようにしたいと考えています(ユーザーを適切なものに自動的にリダイレクトします)。ガード自体をログイン+ルートに依存させることで解決しました。
ルート:
const appRoutes: Routes = [
{ path: 'login', component: LoginComponent, canActivate: [AuthGuard] },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
ガード:
export class AuthGuard implements CanActivate {
private login: UrlTree;
private dash: UrlTree;
constructor(private authSvc: AuthenticationService, private router: Router ) {
this.login = this.router.parseUrl('login');
this.dash = this.router.parseUrl('dashboard');
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
if (this.authSvc.isSignedIn()) {
if (route.routeConfig.path === 'login') {
return this.dash;
} else {
return true;
}
} else {
if (route.routeConfig.path === 'login') {
return true;
} else {
return this.login;
}
}
}
}