[英]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.