如果刷新令牌已过期,我会尝试刷新访问令牌。登录后,我会收到两个令牌并将它们存储在本地存储中。服务器以状态401响应后,我尝试发送刷新令牌,但失败了,看来拦截器在标头内发送了berer访问令牌,而不是刷新令牌
身份验证拦截器
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private authService: LoginService,
private uploadService: ContractUploadService ) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (this.authService.getJwtAccessToken()) {
request = this.addToken(request, this.authService.getJwtAccessToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authService.refreshToken().pipe(
finalize(() => this.isRefreshing = false),
switchMap((token: any) => {
if (token) {
this.refreshTokenSubject.next(token.jwt);
return next.handle(this.addToken(request, token.jwt));
}
this.authService.doLogoutUser();
this.uploadService.stopUploadStatusChecker();
}),
catchError(error => {
this.authService.doLogoutUser();
this.uploadService.stopUploadStatusChecker();
return throwError(error);
})
);
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
}
刷新令牌请求
refreshToken() {
return this.http
.post<any>(BACK_END_URL_REFRESH, {
'refresh_token': this.getRefreshToken()
})
.pipe(
tap((tokens: any) => {
this.storeJwtToken(tokens.jwt);
this.isAuthenticated = true;
}),
catchError((err: any) => {
console.log(err)
this.doLogoutUser();
return throwError(err);
})
);
}
登录
login(user: UserLogin) {
const userData = new FormData();
userData.append('user', user.name);
userData.append('pwd', user.password);
this.http.post<{ access_token: string; refresh_token: string }>(BACK_END_URL, userData).pipe(
finalize(() => this.interactionService.setSpinnerStatus.next(false)),
)
.subscribe(
response => {
if (response.access_token) {
this.isAuthenticated = true;
this.interactionService.setSnackBar('User logged in successfully', 'success');
this.storeTokens(response.refresh_token, response.access_token);
this.extractUserInfoFromToken(response.access_token);
this.router.navigate(['/user-panel']);
}
},
error => {
this.interactionService.setSnackBar('Wrong user name or password', 'error');
}
);
}
本地存储方法
private getRefreshToken() {
return localStorage.getItem(this.REFRESH_TOKEN);
}
private storeJwtToken(jwt: string) {
localStorage.setItem(this.JWT_ACCESS_TOKEN, jwt);
}
private storeTokens(refreshToken, accessToken) {
localStorage.setItem(this.REFRESH_TOKEN, refreshToken);
localStorage.setItem(this.JWT_ACCESS_TOKEN, accessToken);
}
private removeTokens() {
localStorage.removeItem(this.JWT_ACCESS_TOKEN);
localStorage.removeItem(this.REFRESH_TOKEN);
}
[编辑] 尝试实施@Abdellah ASKI建议,但仍然无法正常工作
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (this.authService.getJwtAccessToken() && request.headers.get('No-Auth') !== 'true') {
request = this.addToken(request, this.authService.getJwtAccessToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
refreshToken() {
return this.http
.post<any>(BACK_END_URL_REFRESH, {
refresh_token: this.getRefreshToken(),
'No-Auth': 'true'
})
.pipe(
tap((tokens: any) => {
this.storeJwtToken(tokens.jwt);
this.isAuthenticated = true;
}),
catchError((err: any) => {
this.doLogoutUser();
return throwError(err);
})
);
[Edit2]
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (this.authService.getJwtAccessToken() && !request.headers.has('No-Auth')) {
request = this.addToken(request, this.authService.getJwtAccessToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
答案 0 :(得分:0)
[已更新]
解决此问题的想法是,在每个您不需要发送访问令牌的请求上都添加一个名为No-Auth:true
的标头。
因此,在您的代码中,您需要执行以下操作:
在您的refreshToken()函数中,您需要添加一个新的标头,如下所示:
refreshToken() {
return this.http
.post<any>(BACK_END_URL_REFRESH, {
'refresh_token': this.getRefreshToken(),
'No-Auth': 'true' <<-------<<-------<<-------<<-------
})
.pipe(
....
);
}
在Auth拦截器上,您需要检查此标头(如果存在),而无需添加访问令牌:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (request.headers.has('No-Auth')) { <<-------<<-------<<-------
return next.handle(request);
}
if (this.authService.getJwtAccessToken()) {
request = this.addToken(request, this.authService.getJwtAccessToken());
}
....
}