2017-05-12 3 views
2

내가 토큰을 TTL refresing에 대한 접근 찾지 못했습니다 오랜 시간 후 : 내가 할 innactive 나는 45 분 페이지를 새로 고침하면 2 주각도 - JWT 새로 고침 토큰

: 삼십분 새로 고침 TTL을 getAccessToken() 함수는 만료 된 토큰을 보내고 새로 고친 토큰을 다시 보냅니다. 큰 문제는 내 페이지가 첫 번째 요청 내 토큰 두 번째 요청의 힘을 무효화 할 경우 1 개 이상의 아약스 요청 후 만드는 경우는 빈 토큰

@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); 
} 
} 

내가 요청의 응답을 기다리는 원하는 보내 becauce 내 다시 로그인 할 수 있다는 것입니다 첫 번째 요청

+0

새로 고침 토큰 및 요청을 원활하게 처리해야하는 angular2-jwt의 포크/확장이 있습니다. 아직 시도하지 않았습니까? https://github.com/leonardobazico/angular2-jwt-refresh –

답변

1

는 그리고이 새로운 세션 객체 라이브러리

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); 
} 
}