[英]Implement http request in interceptor angular2
我正在尝试使用httpClientModule处理来自拦截器的 401响应。 身份验证基于JWT,带有accessToken和refreshToken。 如果accessToken过期,我需要请求api以使用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()且令牌已过期时,出现以下错误:
错误=>类型错误:您在期望流的位置提供了“未定义”。 您可以提供一个Observable,Promise,Array或Iterable。
这与这种行为有关吗?
很少有拦截器可以选择完全处理请求本身,并编写新的事件流,而不是调用next.handle()。 这是可以接受的行为,但是请记住,其他拦截器将被完全跳过。 拦截器为单个请求返回事件流上的多个响应也是很少见但有效的。 资源
我终于用不同的实现来管理它。 这是我的拦截器:
@Injectable()
export class JwtService implements HttpInterceptor {
constructor(public inj: Injector){}
private fixUrl(url: string) {
if (url.indexOf('http://') >= 0 || url.indexOf('https://') >= 0)
return url;
else
return APP_CONFIG['apiEndPoint'] + url;
}
intercept(req : HttpRequest<any>, next : HttpHandler) : Observable<HttpEvent<any>> {
// Clone request
var headers = {}
if (APP_CONFIG['accessToken']){
headers = { 'Authorization' : APP_CONFIG['accessToken'] };
}
const cloneRequest = req.clone( { setHeaders : headers });
return next.handle(cloneRequest).do(data => {
if (data instanceof HttpResponse) {
// Some logic
}
})
.catch((res)=> {
if (res.status === 401 || res.status === 403) {
if (APP_CONFIG['accessToken'])
{
const auth = this.inj.get(AuthService);
return auth.getUpdatedAccessToken().flatMap( token => {
// Clone the previous request
let clonedRequestRepeat = req.clone({
headers: req.headers.set('Authorization' , APP_CONFIG['accessToken'] ),
url: this.fixUrl(req.url)
});
// Request agin
return next.handle(clonedRequestRepeat).do(event => {
if (event instanceof HttpResponse) {
console.log('Repeat response of server : ', event);
}
});
});
}else { return Observable.throw('Not authenticated'); }
}
else { // Not 401
return Observable.throw(res);
}
})
}
}
AuthService.ts
getUpdatedAccessToken() : Observable<any>{
return this.http.post(this.api+ 'getaccesstoken', JSON.stringify({refreshToken: APP_CONFIG['refreshToken'] }), { "headers" : this.headers } )
.map((response: any) => {
if (response.code == 0){
APP_CONFIG['accessToken'] = response.accessToken;
}
return response
})
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.