2016-12-16 245 views
1

我有一個個人REST API,我從角度2客戶端調用。我目前的認證過程如下:使用個人api的刷新令牌更新訪問令牌

  1. 用戶登錄使用電子郵件/密碼
  2. Server驗證,併發送USER_DATA,的access_token(JWT)和refresh_token(存儲在數據庫中的不透明令牌)返回到客戶端。
  3. 客戶端根據每個請求發送access_token。

在我的API上,我有端點getAccessToken(String email, String refresh_token),它驗證refresh_token併發出一個新的access_token。

我的問題是:我應該使用什麼方法來請求在使用我的angular2應用程序中的refresh_token之前或之後的新access_token。

我目前想每個HTTP請求的API之前檢查期滿的access_token如下:

if (!tokenNotExpired("accessToken")) { 
    this.classService.getAccessToken().subscribe(
     data => { 
      // store new access_token in localStorage, then make request to get resource. 
      this.classService.createClass().subscribe(
       data => { 
        //success 
       }, error => { 
        //error 
       }) 
     }, error => { 
      // Invalid refresh token, redirect to login page. 
     }); 
} else { 
    this.classService.createClass().subscribe(
     data => { 
      //success 
     }, error => { 
      //error 
     }); 
} 

是否有更好的方法來做到這一點?我正在使用angular2-jwt進行標記驗證。

回答

1

這似乎很好。但是,如果您有多個不同的API調用(例如,不僅僅是createClass(),而且還有updateClass()destroyClass()),您最終可能不得不在源代碼的許多不同位置執行相同的令牌到期檢查,這絕不是件好事。

如何創建一個服務來處理所有呼叫的令牌過期/續約?

此服務將作爲observables的工廠。您告訴它應該聯繫哪個端點以及要發送到端點的數據。該服務將根據您的API請求返回一個觀察值。如果令牌已過期,它會將您的可觀察值包裹在令牌刷新調用中。

這只是一個僞代碼來獲得的總體思路:

class ApiService 
{ 
    constructor (private http: Http){} 

    createRequest (endpoint, payload):Observable<any> 
    { 
     let request = 
     this.http.post(endpoint, payload, {headers:auth}).map(/* ... */); 

     if (tokenExpired()) 
     { 
      return this.refreshToken().flatMap( 
      (token) => {return request}); 
     } 
     else 
      return request; 
    } 

    refreshToken():Observable<string> 
    { 
     /* ... */ 
    } 
} 

有了這項服務,你不必檢查令牌過期其他地方。只要確保您使用該服務來構建您的API調用,即在您的createClass()方法中。

您甚至可以通過允許關閉授權的參數(例如,對於不需要授權的端點)來增強createRequest方法。另一個參數可用於使用不同的HTTP方法(PUT,GET)創建調用。

+0

感謝。你幫了一大堆忙。 – Dapope

0

我試圖模仿好老滑動過期:

在auth.guard.ts:

import { Injectable }     from '@angular/core'; 
import { Router, CanActivate }  from '@angular/router'; 
import { tokenNotExpired, 
     JwtHelper }     from 'angular2-jwt'; 

@Injectable() 
export class AuthGuard implements CanActivate { 
    private jwtHelper = new JwtHelper(); 

    constructor(private router: Router) {} 


    tokenValid() { 
    this.handleSlidingExpiration(); 
    return tokenNotExpired(); 
    } 

    canActivate() { 
    if (tokenNotExpired()) { 
     this.handleSlidingExpiration(); 
     return true; 
    } 

    this.router.navigate(['/login']); 
    return false; 
    } 

    private handleSlidingExpiration() { 
    let token = localStorage.getItem('id_token'); 
    if (!token) { return; } 

    let expirationDate = this.jwtHelper.getTokenExpirationDate(token); 
    let dToken = this.jwtHelper.decodeToken(token); 
    let refreshLimit = new Date((dToken.iat + (dToken.exp - dToken.iat)/2) * 1000); 

    if(new Date() > refreshLimit) { 
     // Here you can make a new side request for the new token and update it in local storage 
    } 
    } 
}