这种情况是在后端调用服务时,如果我收到错误代码表示该服务已过期,则在前端 首先:请求有效的jwt令牌。 第二:在获得有效令牌后重新请求原始的http请求。 第一步成功完成,但第二步却没有。 这是拦截器中的代码
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(catchError(err => {
Log.log("Error Status: " + err.status);
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
this. doRefreshToken(request, next);
}
}
));
}
doRefreshToken(request, next) {
return this.authenticationService.refreshToken().subscribe((resp: HttpResponse<any>) => {
Log.log("in subscripe refresh token")
Log.log(resp.headers.get(this.AUTH_HEADER));
StorageManagementUtil.setLocaltStorage(resp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>resp.body);
},
(error) => { Log.log(error) },
() => {
Log.log("on complete()")
request = this.addAuthenticationToken(request);
return next.handle(request);
});
}
这是刷新令牌服务
refreshToken() {
let map = new TSMap();
map.set(this.RQUEST_BODY_KEY_SESSION_TOKEN, StorageManagementUtil.readFromLocalStorage(StorageManagementUtil.SESSION_TOKEN));
var requsetBody = JSON.stringify(map.toJSON());
let request = new PortalRequestTransaction(requsetBody);
return this.http.post<PortalRsponseTransaction>(fullURL, request, {
observe: 'response',
responseType: 'json'
});
}
这是检查时网络点击的屏幕截图
https://i.ibb.co/vqLTLh2/1.png
问题是,为什么在获取刷新令牌后没有完成对原始服务的调用?以及为什么两次呼叫服务? (如果我们忽略OPTIONS请求类型的内容)。
我是新手,所以我希望我能提供足够的信息来解决问题。
答案 0 :(得分:0)
1)401表示未经授权,看来您没有在请求中发送正确的授权标头(Bearer {JWT-Token})。
2)对于刷新令牌,最好使用rxjs-retry,这将帮助您处理错误或到期时的刷新逻辑
代码如下:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(
retryWhen(err => {
if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
return this. doRefreshToken(request, next);
}
}),
catchError(err => {
Log.log("Error Status: " + err.status);
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
this. doRefreshToken(request, next); // return an observable
}
}
));
}
上面的代码片段,如果有错误,将重试,它将首先刷新令牌,返回一个可观察的对象,然后再次调用getAll。
答案 1 :(得分:0)
此解决方案受此答案using switchMap
的启发 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(
catchError((err) => {
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) {
return this.handleRefreshToken(request, next);
}
})
);
}
handleRefreshToken(request: HttpRequest<any>, next: HttpHandler) {
return this.authenticationService.refreshToken().pipe(
switchMap((tokenResp) => {
StorageManagementUtil.setLocaltStorage(tokenResp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>tokenResp.body);
request = this.addAuthenticationToken(request);
return next.handle(request);
}),
catchError(error => {
if (error.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
})
);
}