[英]Angular 8 suppress HTTP calls before authentication is complete
所以我有一個 API 調用我頁面的 header 部分,它是 app.component.html 的一部分。 然后我的路由模塊中有幾個屏幕有 canActivate。 只有路由到這些屏幕才能觸發 auth.guard 然后進行身份驗證。 但是由於這個菜單代碼在 app.component.html 里面。 甚至在我有令牌之前就已經進行了調用,並且我在 console.log 中出現了 401 錯誤。 有沒有辦法在身份驗證結束之前阻止此調用,即我有刷新、ID 和訪問令牌?
app-routing module
const routes: Routes = [
{ path: 'abc', component:abcComponent , canActivate: [AuthGuard] },
{path: 'xyz', component:xyzComponent , canActivate: [AuthGuard] }
];
app.component.ts
ngOnIt(){
this.httpService.getMenu().subscribe((response) => {
this.menuArray=response
});
}
export class TokenInterceptorService implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url == environment.authTokenPostUrl) {
const tokenreq = req.clone({});
return next.handle(tokenreq);
} else {
const tokenreq = this.addToken(req);
return next.handle(tokenreq).pipe(
catchError((error) => {
const cookie = this.injector.get(CookieService);
if (error.status === 401) {
return this.handle401Error(tokenreq, next);
} else {
return throwError(error);
}
})
);
}
}
private addToken(request: HttpRequest<any>) {
const authservice = this.injector.get(AuthService);
const headers = { Authorization: `Bearer ${authservice.setIdToken()}` };
return request.clone({
setHeaders: headers,
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
const authservice = this.injector.get(AuthService);
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return authservice.refreshToken().pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.id_token);
return next.handle(this.addToken(request));
})
);
} else {
return this.refreshTokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((jwt) => {
return next.handle(this.addToken(request));
})
);
}
}
}
所以我試過了
ngOnIt(){
if(this.cookieService.get('refresh_token'))
this.httpService.getMenu().subscribe((response) => {
this.menuArray=response
});
}
}
但是這個邏輯不起作用,因為身份驗證是在觸發此調用之后發生的。
有辦法解決這個問題嗎?
雖然 RxJS 解決方案可能更優雅(我建議您深入研究),但我將 go 逆流而上,並提供更“老式的角度”解決方案。 它使用簡單的屬性,看不到 $ 符號。 對於經驗不足的程序員來說,這可能是一個不錯的選擇,同時保持了可維護性。
在您的 AuthService 中,創建一個名為authenticated
的屬性。 驗證后將其設置為true
。
class AuthService {
authenticated = false;
authenticate(params) {
this.http.post([authentication stuff]).subscribe(() => {
// do what you do now
this.authenticated = true;
}
}
然后,在單獨的<app-menu>
組件中將菜單代碼分開。
class MenuComponent {
ngOnInit() {
this.httpService.getMenu().subscribe((response) => {
this.menuArray=response
});
}
}
在主AppComponent
中,鏈接 auth 服務並通過 getter 代理已authenticated
的屬性。
class AppComponent {
get authenticated() { return this.authService.authenticated; }
constructor(authService: AuthService) {}
}
然后,在AppComponent
的模板中使用*ngIf
來顯示菜單組件。
<app-menu *ngIf="authenticated"></app-menu>
另一種方法是使用經過authenticated$
BehaviourSubject
,但我會把它留給其他答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.