2017-12-10 32 views
1

Angularインターセプタでこのロジックを実装して、すべてのリクエストをインターセプトし、Authorizationヘッダーを挿入しました。また、401 Unauthorizedレスポンスのすべてをキャッチします。この場合、トークンを最初にリフレッシュしようとした後、元のリクエストを再試行します。Angularインターセプタのトークンが期限切れになったときに更新する

トークンが期限切れになったときにどのリクエストが401 Unauthorizedになるかを知ることができるという点を除いて、これはうまくいきます。トークンが期限切れになった場合は、実際のリクエストを送信する前にトークンをリフレッシュしたいと思います。

HERE @todoとマークされた場所にリフレッシュされたトークンが必要です。または、concatMapでリフレッシュ機能を呼び出し、元のリクエストを完了したら、残りのコードを実行してください。

どうすればいいですか?ここで私がこれまで持っているものです。

import {HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse} from '@angular/common/http'; 
import {AuthService} from './auth.service'; 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/concatMap'; 
import 'rxjs/add/operator/concat'; 
import 'rxjs/add/operator/catch'; 
import {Injectable, Injector} from '@angular/core'; 
import {JwtHelper} from 'angular2-jwt'; 

@Injectable() 
export class AuthInterceptor implements HttpInterceptor { 
    private auth: AuthService; 
    jwtHelper = new JwtHelper(); 

    constructor(private injector: Injector) { 
    } 
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> { 
     this.auth = this.injector.get(AuthService); 

     // this.auth.token is an instance of Observable<string> (list of tokens) 
     return this 
      .auth 
      // Get the latest token from the auth service. 
      .token 
      // Map the token to a request with the right header set. 
      .map(token => { 
       const cloned = request.clone({ headers: request.headers.set('Authorization', `Bearer ${token}`) }); 
       if (this.jwtHelper.isTokenExpired(token)) { 
        // here I already know that the request is not necessary, as will result in 401 
        console.log('WARN: refresh'); 
        // HERE @todo: refresh the token before further processing 
       } 
       return cloned; 
      }) 
      // Execute the request on the server. 
      .concatMap((cloned) => { 
       return next.handle(cloned); 
      }) 
      // Catch the 401 and handle it by refreshing the token and restarting the chain 
      // (where a new subscription to this.auth.token will get the latest token). 
      .catch((err, restart) => { 
       // If the request is 401 unauthorized, try refreshing the token before restarting. 
       if (err instanceof HttpErrorResponse && err.status === 401) { 
         // this.auth.refreshToken is instance of Observable<any> 
         return this.auth.refreshToken 
          .concat(restart) 
          .catch((error, caught) => { 
            // in case of failed refresh token, logout and redirect to login route 
            if (error instanceof HttpErrorResponse && err.status === 401) { 
             this.auth.logout(true); 
            } 
            throw caught; 
           } 
          ); 
       } 

       throw(err); 
      }); 
    } 
} 

答えて

-1
import {HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse} from '@angular/common/http'; 
import {AuthService} from './auth.service'; 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/concatMap'; 
import 'rxjs/add/operator/concat'; 
import 'rxjs/add/operator/catch'; 
import {Injectable, Injector} from '@angular/core'; 
import {JwtHelper} from 'angular2-jwt'; 

@Injectable() 
export class AuthInterceptor implements HttpInterceptor { 
    private auth: AuthService; 
    jwtHelper = new JwtHelper(); 

    constructor(private injector: Injector) { 
    } 
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> { 
     this.auth = this.injector.get(AuthService); 

     // this.auth.token is an instance of Observable<string> (list of tokens) 
     return this 
      .auth 
      // Get the latest token from the auth service. 
      .token 
      // Map the token to a request with the right header set. 
      .map(token => { 
       const cloned = request.clone({ headers: request.headers.set('Authorization', `Bearer ${token}`) }); 
       if (this.jwtHelper.isTokenExpired(token)) { 
        // here I already know that the request is not necessary, as will result in 401 
        console.log('WARN: refresh'); 
        // HERE @todo: refresh the token before further processing 
        return this.auth.refreshToken 
           .flatMap((token) => { return cloned; }); 
       } 
       return cloned; 
      }) 
      // Execute the request on the server. 
      .concatMap((cloned) => { 
       return next.handle(cloned); 
      }) 
      // Catch the 401 and handle it by refreshing the token and restarting the chain 
      // (where a new subscription to this.auth.token will get the latest token). 
      .catch((err, restart) => { 
       // If the request is 401 unauthorized, try refreshing the token before restarting. 
       if (err instanceof HttpErrorResponse && err.status === 401) { 
         // this.auth.refreshToken is instance of Observable<any> 
         return this.auth.refreshToken 
          .concat(restart) 
          .catch((error, caught) => { 
            // in case of failed refresh token, logout and redirect to login route 
            if (error instanceof HttpErrorResponse && err.status === 401) { 
             this.auth.logout(true); 
            } 
            throw caught; 
           } 
          ); 
       } 

       throw(err); 
      }); 
    } 
} 
+0

はちょうどトークンをリフレッシュし、要求を再送信します。例えば、を参照されたい。 https://stackoverflow.com/questions/47417899/angular-4-and-oauth-intercept-401-responses-refresh-the-access-token-and-retr – Eliseo

関連する問題