簡體   English   中英

在攔截器angular2中實現http請求

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM