CanGuardateを実装するAuthGuard(ルーティングに使用)があります。
canActivate() {
return this.loginService.isLoggedIn();
}
私の問題は、CanActivate-resultがhttp-get-resultに依存していることです。-LoginServiceはObservableを返します。
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).map(response => response.ok);
}
それらをどのようにまとめることができますか-CanActivateをバックエンドの状態に依存させますか?
「@ angular/router」を最新のものにアップグレードする必要があります。例:「3.0.0-alpha.8」
AuthGuard.tsの変更
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private loginService:LoginService, private router:Router) { }
canActivate(next:ActivatedRouteSnapshot, state:RouterStateSnapshot) {
return this.loginService.isLoggedIn().map(e => {
if (e) {
return true;
}
}).catch(() => {
this.router.navigate(['/login']);
return Observable.of(false);
});
}
}
ご質問があれば、私に尋ねてください!
Angular 5およびRxJS 5.5 に対するKery Huの回答を更新します。ここでcatch
name__演算子は非推奨です。これで、catchError演算子をpipe および lettable演算子 と組み合わせて使用する必要があります。
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { catchError, map} from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private loginService: LoginService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.loginService.isLoggedIn().pipe(
map(e => {
if (e) {
return true;
} else {
...
}
}),
catchError((err) => {
this.router.navigate(['/login']);
return of(false);
})
);
}
}
canActivate() は、戻り値としてObservable<boolean>
を受け入れます。ガードはObservableが解決して値を確認するまで待機します。 'true'の場合、チェックに合格します。それ以外の場合(その他のデータまたはスローされたエラー)はルートを拒否します。
.map
演算子を使用して、次のようにObservable<Response>
をObservable<boolean>
に変換できます。
canActivate(){
return this.http.login().map((res: Response)=>{
if ( res.status === 200 ) return true;
return false;
});
}
私はこの方法でそれをやった:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.auth(() => this.router.navigate(['/user/sign-in']));}
ご覧のとおり、http呼び出しが失敗した場合の対処方法をフォールバック関数をuserService.authに送信しています。
そして、userServiceには次のものがあります:
import 'rxjs/add/observable/of';
auth(fallback): Observable<boolean> {
return this.http.get(environment.API_URL + '/user/profile', { withCredentials: true })
.map(() => true).catch(() => {
fallback();
return Observable.of(false);
});}
これはあなたを助けるかもしれません
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthState } from 'src/app/shared/state';
export const ROLE_SUPER = 'ROLE_SUPER';
@Injectable()
export class AdminGuard implements CanActivate {
@Select(AuthState.userRole)
private userRoles$: Observable<string[]>;
constructor(private router: Router) {}
/**
* @description Checks the user role and navigate based on it
*/
canActivate(): Observable<boolean> {
return this.userRoles$.pipe(
take(1),
map(userRole => {
console.log(userRole);
if (!userRole) {
return false;
}
if (userRole.indexOf(ROLE_SUPER) > -1) {
return true;
} else {
this.router.navigate(['/login']);
}
return false;
})
);
} // canActivate()
} // class
サブスクライブを呼び出さずにどのように機能しますか? .net APIを通じてこれを呼び出すと、何も返されません。このように認証ガードサービスでサブスクライブを呼び出す必要があり、それから実際のAPI呼び出しのみを行います。しかし、サブスクライブは非同期なので、私のcanActivateガードは機能せず、ユーザーはページに入ることができます。
AuthGauard service:
canActivate() { this.loginService.isLoggedIn()
.subscribe(response => {
if (!response) return false;})
return true;
}
loginService:
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).pipe(map(response => response.ok));
}