在 angular 5 中刷新访问令牌时出现问题
Issue while refreshing access token in angular 5
如果用户收到未经授权的错误,我想刷新令牌。我试图在拦截器中处理这个问题。下面是代码:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
fn.refreshToken(req, next);
}
}
});
}
我有函数 refreshToken,我试图调用 API 来刷新令牌:
refreshToken(req, next) {
const headers = new HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded');
const body = new HttpParams()
.set('refresh_token', localStorage.getItem('refreshToken'));
this._http.post('/refreshtoken', body.toString(), {headers}).subscribe(
(data) => {
const header = `Bearer ${(<any>data).accessToken}`;
const newRequest = req.clone({ headers: req.headers.set('Authorization', header)});
return next.handle(newRequest);
}),
(err) => {
console.log(err);
}
}
但是上面代码的问题是我无法调用克隆的请求。只有在我调用它的订阅方法时才会触发请求。如下图:
return next.handle(newRequest).subscribe();
我想如果令牌过期,调用服务来刷新令牌并重新发送失败的原始请求。再调用失败的原始请求的subscribe方法。
请让我知道我的方法是否正确。
如果是,那么我在这里缺少什么。
拦截器必须 return 一个 Observable 并且可以调用 next.handle(req)
本身所以我认为你可以调用 next.handle(req)
两次但更好的更多 "Rx" 解决方案是使用 catch
运算符并合并原始源 Observable。此外,您还需要将 refreshToken
更改为 return 一个 Observable,并且您可能希望使用 do()
.
存储新令牌
refreshToken(...): Observable<any> {
return this._http.post('/refreshtoken', ...)
.do(/* save token here */);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.catch((err, source) => {
if (err instanceof HttpErrorResponse && err.status === 401) {
return this.refreshToken(...)
.concatMap(() => next.handle(req /* ... or updated req */ ));
// or you could use .concatMap(() => source) to trigger the same request again
}
throw err;
})
}
如果用户收到未经授权的错误,我想刷新令牌。我试图在拦截器中处理这个问题。下面是代码:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
fn.refreshToken(req, next);
}
}
});
}
我有函数 refreshToken,我试图调用 API 来刷新令牌:
refreshToken(req, next) {
const headers = new HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded');
const body = new HttpParams()
.set('refresh_token', localStorage.getItem('refreshToken'));
this._http.post('/refreshtoken', body.toString(), {headers}).subscribe(
(data) => {
const header = `Bearer ${(<any>data).accessToken}`;
const newRequest = req.clone({ headers: req.headers.set('Authorization', header)});
return next.handle(newRequest);
}),
(err) => {
console.log(err);
}
}
但是上面代码的问题是我无法调用克隆的请求。只有在我调用它的订阅方法时才会触发请求。如下图:
return next.handle(newRequest).subscribe();
我想如果令牌过期,调用服务来刷新令牌并重新发送失败的原始请求。再调用失败的原始请求的subscribe方法。
请让我知道我的方法是否正确。
如果是,那么我在这里缺少什么。
拦截器必须 return 一个 Observable 并且可以调用 next.handle(req)
本身所以我认为你可以调用 next.handle(req)
两次但更好的更多 "Rx" 解决方案是使用 catch
运算符并合并原始源 Observable。此外,您还需要将 refreshToken
更改为 return 一个 Observable,并且您可能希望使用 do()
.
refreshToken(...): Observable<any> {
return this._http.post('/refreshtoken', ...)
.do(/* save token here */);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.catch((err, source) => {
if (err instanceof HttpErrorResponse && err.status === 401) {
return this.refreshToken(...)
.concatMap(() => next.handle(req /* ... or updated req */ ));
// or you could use .concatMap(() => source) to trigger the same request again
}
throw err;
})
}