2017-05-12 91 views
2

後很長一段時間我沒有找到有關refresing令牌 TTL的方法:如果我刷新頁面後45分鐘innactive然後我做一個2周角 - 智威湯遜刷新令牌

:30分鐘 刷新TTL getAccessToken()函數發送過期的令牌,然後發送給我一個刷新的令牌。最大的問題是,如果我的網頁,使超過1個AJAX請求,那麼如果第一個請求無效我令牌的第二個請求力我重新登錄becauce其發送空的令牌

@NgModule({ 
providers: [ 
    { 
     provide: AuthHttp, 
     useFactory: authHttpServiceFactory, 
     deps: [Http, RequestOptions, Router] 
    } 
] 
}) 

export function authHttpServiceFactory(http: Http, options: RequestOptions, router: Router) { 
return new AuthHttp(new AuthConfig({ 
    tokenName: 'token', 
    tokenGetter: (() => getAccessToken(http,router)), 
    //tokenGetter: (() => localStorage.getItem('JWToken')), 
    globalHeaders: [{'Content-Type': 'application/json'}], 
    noJwtError: true, 
}), http, options); 
} 


function getAccessToken(http: Http, router:Router): Promise<string> { 

let jwtHelper: JwtHelper = new JwtHelper(); 

let accessToken = localStorage.getItem('JWToken'); 

if(accessToken == '' || !accessToken || accessToken == undefined || accessToken == null){ 
    router.navigate(['./admin/login']); 
    return; 
} 


if (jwtHelper.isTokenExpired(accessToken)) { 
    return new Promise((resolve, reject) => { 
     let refreshTokenService: RefreshTokenService = new RefreshTokenService(http); 
     refreshTokenService.refreshToken(accessToken).subscribe((res: any) => { 
      res = res.json(); 

      if(res.token) { 
       localStorage.setItem('JWToken', res.token); 
       resolve(res.token); 

      }else{ 
       localStorage.removeItem('JWToken'); 

       router.navigate(['./admin/login']); 
      } 
     }); 
    }); 
} else { 
    return Promise.resolve(accessToken); 
} 
} 

我想請求等待響應第一個請求

+0

有一個應該無縫處理刷新令牌和請求的angular2-jwt的fork/extension。還沒有嘗試過呢https://github.com/leonardobazico/angular2-jwt-refresh –

回答

1

這是新HttpClient庫

import {Injectable, Injector} from "@angular/core"; 
import {HttpEvent, HttpHandler, HttpInterceptor, HttpResponse} from "@angular/common/http"; 
import {HttpRequest} from "@angular/common/http"; 
import {Observable} from "rxjs/Observable"; 
import {SiteService} from "../services/site.service"; 
import {Router} from "@angular/router"; 
import {LoadingService} from "../../components/loading/loading.service"; 
import {AuthenticationService} from "../services/authentication.service"; 

@Injectable() 
export class AuthInterceptor implements HttpInterceptor { 

constructor(private router: Router, 
      private siteService: SiteService, 
      private loadingService: LoadingService, 
      private injector: Injector) { 
} 



private fixUrl(url: string) { 
    if (url.indexOf('http://') >= 0 || url.indexOf('https://') >= 0) 
     return url; 
    else 
     return this.siteService.apiDomain() + url; 
} 

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 

    let clonedRequest; 
    if (this.siteService.getJWToken() !== null) { 
     clonedRequest = req.clone({ 
      headers: req.headers.set('Authorization', 'Bearer ' + this.siteService.getJWToken()), 
      url: this.fixUrl(req.url) 
     }); 
    } else { 
     clonedRequest = req.clone({ 
      url: this.fixUrl(req.url) 
     }); 
    } 

    let authenticationService = this.injector.get(AuthenticationService); 

    this.loadingService.start(); 
    const started = Date.now(); 
    return next.handle(clonedRequest) 
     .do(event => { 
      if (event instanceof HttpResponse) { 

       const elapsed = Date.now() - started; 
       console.log('%c Request for ' + this.fixUrl(req.urlWithParams) + ' took ' + elapsed + ' ms.', 'background: #222; color: yellow'); 
      } 
     }) 
     ._finally(() => { 
      this.loadingService.stop(); 
     }) 
     .catch((res) => { 
      if ((res.status === 401 || res.status === 403) && res.error.error === 'token_expired') { 
       this.loadingService.start(); 
       return authenticationService.refreshToken().flatMap((data: any) => { 
        this.loadingService.stop(); 
        if (data.token !== '') { 
         this.siteService.setCurrentUser(data.user); 
         this.siteService.setCurrentUserPermissions(data.permissions); 
         this.siteService.setJWToken(data.token); 
        } else { 
         this.siteService.removeCurrentUser(); 
         this.siteService.removeCurrentUserPermissions(); 
         this.siteService.removeJWToken(); 
         this.router.navigate(['./auth/login']); 
         return Observable.throw(res); 
        } 
        let clonedRequestRepeat = req.clone({ 
         headers: req.headers.set('Authorization', 'Bearer ' + this.siteService.getJWToken()), 
         url: this.fixUrl(req.url) 
        }); 
        return next.handle(clonedRequestRepeat).do(event => { 
         if (event instanceof HttpResponse) { 

          const elapsed = Date.now() - started; 
          console.log('%c Request for ' + req.urlWithParams + ' took ' + elapsed + ' ms.', 'background: #222; color: yellow'); 
         } 
        }); 
       }) 
      } else if (res.status === 400 && res.error.error === 'token_not_provided') { 
       this.router.navigate(['./auth/login']); 
       return Observable.throw(res); 
      } else if (res.status === 401 && res.error.error === 'token_invalid') { 
       this.router.navigate(['./auth/login']); 
       return Observable.throw(res); 
      } else { 
       return Observable.throw(res); 
      } 

     }); 

} 
} 

注射器不要忘記發送緩存(瀏覽器)頭到後端響應至少幾秒鐘。

1
  • 發送採用了特殊的服務
  • 存儲與可觀察到該服務中的緩衝區401個迴應一起應用中的所有HTTP請求,你會返回給調用者。第一個401發送令牌刷新請求
  • 當你有新的令牌時,用新的令牌重複緩衝區中的所有請求,並用新的響應調用它們的可觀察對象。
+0

任何示例代碼? – Michalis

0
function getAccessToken(http: Http, router: Router, refreshTokenService: RefreshTokenService): Promise<string> { 

let jwtHelper: JwtHelper = new JwtHelper(); 

let accessToken = localStorage.getItem('JWToken'); 

if (accessToken == '' || !accessToken || accessToken == undefined || accessToken == null) { 
    router.navigate(['./admin/login']); 
    return; 
} 

if (jwtHelper.isTokenExpired(accessToken)) { 

    let waitPeriod = (!refreshTokenService.wait); 

    refreshTokenService.wait = true; 

    return new Promise((resolve, reject) => { 

     if (waitPeriod) { 
      refreshTokenService.refreshToken(accessToken).subscribe((res: any) => { 
       res = res.json(); 

       if (res.token) { 
        localStorage.setItem('JWToken', res.token); 
        resolve(res.token); 
        refreshTokenService.wait = false; 
       } else { 
        localStorage.removeItem('JWToken'); 
        router.navigate(['./admin/login']); 
       } 

      }); 
     } else { 
      let interval = setInterval(function() { 
       if(refreshTokenService.wait == false) { 
        resolve(localStorage.getItem('JWToken')); 
        clearInterval(interval); 
       } 
      }, 500); 
     } 

    }); 
} else { 
    return Promise.resolve(accessToken); 
} 
}