gpt4 book ai didi

jwt - Angular 5 HttpClient 拦截器 JWT 刷新 token 无法捕获 401 并重试我的请求

转载 作者:行者123 更新时间:2023-12-04 17:04:58 25 4
gpt4 key购买 nike

我正在尝试实现对 401 响应的捕获并尝试获取基于 Angular 4 Interceptor retry requests after token refresh 的刷新 token .我试图实现同样的事情,但我永远无法重试该请求,我真的不确定这是否是应用刷新 token 策略的最佳方法。
这是我的代码:

@Injectable()
export class AuthInterceptorService implements HttpInterceptor {
public authService;
refreshTokenInProgress = false;
tokenRefreshedSource = new Subject();
tokenRefreshed$ = this.tokenRefreshedSource.asObservable();
constructor(private router: Router, private injector: Injector) { }
authenticateRequest(req: HttpRequest<any>) {
const token = this.authService.getToken();
if (token != null) {
return req.clone({
headers: req.headers.set('Authorization', `Bearer ${token.access_token}`)
});
}
else {
return null;
}
}
refreshToken() {
if (this.refreshTokenInProgress) {
return new Observable(observer => {
this.tokenRefreshed$.subscribe(() => {
observer.next();
observer.complete();
});
});
} else {
this.refreshTokenInProgress = true;

return this.authService.refreshToken()
.do(() => {
this.refreshTokenInProgress = false;
this.tokenRefreshedSource.next();
}).catch(
(error) => {
console.log(error);
}
);
}
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.injector.get(AuthenticationService);
request = this.authenticateRequest(request);
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
return this.refreshToken()
.switchMap(() => {
request = this.authenticateRequest(request);
console.log('*Repeating httpRequest*', request);
return next.handle(request);
})
.catch(() => {
return Observable.empty();
});
}
}
});
}
}

问题是 SwitchMap 永远无法到达......
if (err.status === 401) {
return this.refreshToken()
.switchMap(() => {

还有 do 运算符...
return this.authService.refreshToken()
.do(() => {

所以这把我带到了我的 authService refreshToken 方法......
refreshToken() {
let refreshToken = this.getToken();

refreshToken.grant_type = 'refresh_token';
refreshToken.clientId = environment.appSettings.clientId;
return this.apiHelper.httpPost(url, refreshToken, null)
.map
(
response => {
this.setToken(response.data, refreshToken.email);
return this.getToken();
}
).catch(error => {

return Observable.throw('Please insert credentials');
});
}
}

它返回一个映射的 observable,我知道如果我替换了 do in...
return this.authService.refreshToken()
.do(() => {

订阅我会打破我猜的可观察链。我迷路了,我已经玩了很长时间没有解决方案。 :D

最佳答案

我很高兴你喜欢我的解决方案。我将在此处仅提供最终解决方案,但如果有人想知道我休闲的过程,请转到此处:Refresh Token OAuth Authentication Angular 4+

好的,首先我创建了一个服务来保存 的状态刷新 token 请求 并且 Observable 可以知道请求何时完成。

这是我的服务:

@Injectable()
export class RefreshTokenService {
public processing: boolean = false;
public storage: Subject<any> = new Subject<any>();

public publish(value: any) {
this.storage.next(value);
}
}

I noticed that It was better if I have two Interceptors one to refresh the token and handle that and one to put the Authorization Header if exist.



这是刷新 token 的拦截器:
@Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {

constructor(private injector: Injector, private tokenService: RefreshTokenService) {
}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const auth = this.injector.get(OAuthService);
if (!auth.hasAuthorization() && auth.hasAuthorizationRefresh() && !this.tokenService.processing && request.url !== AUTHORIZE_URL) {
this.tokenService.processing = true;
return auth.refreshToken().flatMap(
(res: any) => {
auth.saveTokens(res);
this.tokenService.publish(res);
this.tokenService.processing = false;
return next.handle(request);
}
).catch(() => {
this.tokenService.publish({});
this.tokenService.processing = false;
return next.handle(request);
});
} else if (request.url === AUTHORIZE_URL) {
return next.handle(request);
}

if (this.tokenService.processing) {
return this.tokenService.storage.flatMap(
() => {
return next.handle(request);
}
);
} else {
return next.handle(request);
}
}
}

所以在这里我等待刷新 token 可用或失败,然后我释放需要授权 header 的请求。

这是放置授权 header 的拦截器:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const auth = this.injector.get(OAuthService);
let req = request;
if (auth.hasAuthorization()) {
req = request.clone({
headers: request.headers.set('Authorization', auth.getHeaderAuthorization())
});
}

return next.handle(req).do(
() => {},
(error: any) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
auth.logOut();
}
}
});
}
}

我的主要模块是这样的:
@NgModule({
imports: [
...,
HttpClientModule
],
declarations: [
...
],
providers: [
...
OAuthService,
AuthService,
RefreshTokenService,
{
provide: HTTP_INTERCEPTORS,
useClass: RefreshTokenInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}

欢迎任何反馈,如果我做错了什么,请告诉我。我正在使用 进行测试角 4.4.6 但我不知道它是否适用于 angular 5,我认为应该可以。

关于jwt - Angular 5 HttpClient 拦截器 JWT 刷新 token 无法捕获 401 并重试我的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47705480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com