Angular 8在身份验证完成之前禁止HTTP调用



因此,我有一个API调用,用于我的页面的标题部分,这是app.component.html的一部分。然后,我的路由模块中有几个屏幕,可以激活。只有路由到这些屏幕才能触发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解决方案可能更优雅(我建议您深入研究(,但我将逆流而上,提供一个更"老派棱角分明的";解决方案它使用简单的属性,看不到$符号。对于经验不足的程序员来说,这可能是一个很好的选择,同时保留了可维护性。

在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中,链接身份验证服务并通过getter代理authenticated属性。

class AppComponent {
get authenticated() { return this.authService.authenticated; }
constructor(authService: AuthService) {}
}

然后,在AppComponent的模板中,使用*ngIf来显示菜单组件。

<app-menu *ngIf="authenticated"></app-menu>

另一种选择是使用authenticated$BehaviourSubject,但我将把它留给其他答案。

最新更新