我正在尝试使用角度拦截器实现刷新令牌功能。这是我要遵循的分步程序
将访问令牌存储在本地存储中。将此令牌添加到授权标头中。
如果访问令牌已过期,请发送刷新令牌(存储在数据库中)并生成一个新令牌。
在以下代码中,我试图实现相同的功能。但是问题是当访问令牌过期时,当前的HTTP请求无法执行(给出401错误)。我必须重新加载该页面才能使该HTTP请求正常工作。如何避免这种情况?
interceptor.ts
export class HttpErrorInterceptor implements HttpInterceptor {
constructor(private router: Router, private loginService: LoginService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const jwt = localStorage.getItem('token')
if (jwt) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${jwt}`
}
});
}
if (!request.headers.has('Content-Type')) {
request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
}
return next.handle(request)
.pipe(
retry(1),
catchError((error: HttpErrorResponse) => {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// client-side error
errorMessage = `${error.error.message}`;
} else {
// console.log(error)
switch (error.status) {
case 401: {
console.log(error.error.error.message)
console.log(error)
if (error.error.error.message.includes('jwt expired')) {
console.log(true)
this.handle401Error(request, next)
}
else {
console.log(false)
this.router.navigate(['login'])
}
}
default:
//window.alert(error.error.error.message)
return throwError(error);
}
// server-side error
// errorMessage = `${error.status}\n ${error.message}`;
}
//\ window.alert(errorMessage);
// return throwError(errorMessage);
})
)
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
console.log('refresh token')
const refreshToken = localStorage.getItem('refreshtoken')
console.log(refreshToken)
this.loginService.refresh_token(refreshToken)
.pipe(untilDestroyed(this))
.subscribe(data => {
console.log(data)
localStorage.setItem('token', data.accessToken)
const jwt = localStorage.getItem('token')
console.log('401', jwt)
if(jwt) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${jwt}`
}
});
}
if (!request.headers.has('Content-Type')) {
request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
}
return next.handle(request);
})
}
}
答案 0 :(得分:-1)
您可以像这样使用s.th:
getposts() {
return this.http.post<any>(`${config.apiUrl}/post`, {
'type': 1
}).pipe(
tap(() => this.doLogoutUser()),
mapTo(true),
catchError(error => {
if(error.status===401){
return this.http.post<any>(`${config.apiUrl}/post`, {
'type': 1
});
}
}));
}
还添加了tis行以捕获拦截器的错误以引发错误:
return throwError(errorMessage);
因此您可以重试请求http.post的捕获错误,而无需重新加载页面