【发布时间】:2021-01-24 07:18:57
【问题描述】:
所以我有一个 API 调用我的页面的标题部分,它是 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;
intercept返回一个 observable,所以你可以例如公开一个可观察的令牌,从而阻止拦截器中的请求,直到它可用。但请注意它是ngOnInit,这就是为什么 Angular recommends 将接口用于生命周期方法。
标签: angular typescript authentication jwt-auth angular-http-interceptors