【发布时间】:2023-03-19 00:19:01
【问题描述】:
我正在尝试使用 httpClientModule 处理来自 interceptor 的 401 响应。身份验证基于 JWT,带有 accessToken 和 refreshToken。如果accessToken过期了,我需要用refreshToken请求api获取一个新的。我想在应该生成新令牌时阻止请求,获取一个新令牌,然后附加新的 accessToken 发出请求。
这样,从拦截器发出http请求的最佳方法是什么?
我的拦截器:
@Injectable()
export class JwtService implements HttpInterceptor {
constructor(public inj: Injector){}
intercept(req : HttpRequest<any>, next : HttpHandler) : Observable<HttpEvent<any>> {
if ( this.shouldGenerateNewAccessToken(req.url) ){
const auth = this.inj.get(AuthService);
auth.getNewAccessToken().then( token => {
if (token){
const headers = { 'Authorization' : token };
const clone = req.clone( { setHeaders : headers } );
return next.handle(clone);
} else { return next.handle(req); }
}, error => {
return next.handle(req);
});
}
else {
if (APP_CONFIG['accessToken']){
const headers = { 'Authorization' : APP_CONFIG['accessToken'] };
const clone = req.clone( { setHeaders : headers });
return next.handle(clone);
} else {
return next.handle(req);
}
}
}
shouldGenerateNewAccessToken(url : string) : Boolean {
let lastupdate = APP_CONFIG['accessTokenTimestamp'];
let now = new Date().getTime();
// Let say the token expires after 5s
if ((now - lastupdate) > 5000 && APP_CONFIG['refreshToken'] && url != APP_CONFIG['apiEndPont']+'getaccesstoken'){
return true;
}
else
return false;
}
授权逻辑
getNewAccessToken() : Promise<any>{
return new Promise( (resolve, reject)=>{
this.http.post(this.api+ 'getaccesstoken', JSON.stringify({refreshToken: APP_CONFIG['refreshToken'] }), { "headers" : this.headers } ).subscribe( data => {
let res : any = data;
APP_CONFIG['accessToken'] = res.accessToken;
APP_CONFIG['accessTokenTimestamp'] = new Date().getTime();
resolve(APP_CONFIG['accessToken']);
}, err => {console.log('error'); reject(null); })
});
}
getuserinfos(){
return this.http.get(this.api+ 'getuserinfos', { "headers" : this.headers } ).subscribe( data => {
console.log('result getUserInfos =>', data);
},
( err : HttpErrorResponse ) => {
if ( err.error instanceof Error ) { console.log('An error occurred requete login:', err.error.message); }
else {
console.log('error => ', err)
}
});
}
当我调用 getUserInfos() 并且令牌已过期时,我收到以下错误:
error => TypeError:您在预期流的位置提供了“未定义”。您可以提供 Observable、Promise、Array 或 Iterable。
这是否与此行为有关?
更罕见的是,拦截器可能会选择完全处理请求本身,并组成一个新的事件流,而不是调用 next.handle()。这是可以接受的行为,但请记住,进一步的拦截器将被完全跳过。拦截器在单个请求的事件流上返回多个响应也是罕见但有效的。 Source
【问题讨论】:
-
你是如何调用 getUserInfos() 的?
-
这是来自我的组件的简单调用:this.authService.getuserinfos()(我猜前后的逻辑不相关,所以我没有将其添加到问题中)
-
this.authService.getuserinfos().subscribe() 还是 this.authService.getuserinfos().then() ?
-
问题不在这里没关系。我可以从 getUserInfos 生成 Promise 或 Observable 并从请求中解析/拒绝答案,这与 getuserinfos() 中的 console.log() 相同
标签: javascript angular http typescript