簡體   English   中英

帶有refresh_token的Angular5 Http攔截器

[英]Angular5 Http Interceptor with refresh_token

我正在嘗試在Angular5的Http攔截器中實現access_token / refresh_token。 我遇到的問題是,獲取刷新令牌后,我無法再次撥打電話。 因此,當我收到401錯誤(access_token過期)時,我使用refresh_token獲得了一個新的access_token,直到這里一切正常。 接下來,我應該使用新的access_token再次進行初始調用,因此我嘗試使用第二個

return next.handle(req);

但這不起作用。 因此,當我第一次單擊並且令牌已過期時,應用程序成功獲取了一個新令牌並將其寫入localStorage,但是不再進行首次調用。 如果再次單擊,將成功進行初始呼叫(使用正確存儲在上一次單擊中的新訪問令牌)。 就像我無法擺脫困境。 也許我在犯一個愚蠢的錯誤。

貝婁是我的代碼。請指教。 謝謝!

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
    let access_token, refresh_token;
    if (localStorage.currentUser) {
        access_token = JSON.parse(localStorage.currentUser).access_token;
        refresh_token = JSON.parse(localStorage.currentUser).refresh_token;

        if(access_token){
            req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + access_token) });
        }
    }
    return next.handle(req)
        .catch((error, caught) => {
            if (this.isAuthError(error)) {
                return this._auth.getRefreshToken().map((resp) => {
                    let user = resp.json();
                    localStorage.setItem('currentUser', JSON.stringify(user));
                    access_token = JSON.parse(localStorage.currentUser).access_token;
                    req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + access_token) });
                    return next.handle(req);
                }); 
            } else {
                return Observable.throw(error);
            }
        })
}

您需要使用flatMap()而不是map(),如下所示:

        ....
        if (this.isAuthError(error)) {
            return this._auth.getRefreshToken().flatMap((resp) => {
        ....                                    ^^^^^^^
                                                 here

否則,您的解決方案對我來說看起來不錯。

在攔截中,您需要設置標題。

if(access_token){
            req = req.clone({setHeaders: 
            {Authorization: `Bearer ${access_token}`}
        });
}

您需要對其他令牌執行相同的操作。

我做了類似的事情:

if ( this._auth.isValidToken() )
  token = this._auth.getValidToken();
  req = this.addToken(req, this._auth.getToken());
  return next.handle(req);
}

// The getNewAccessToken is an observable
return this._auth.getNewAccessToken().pipe(switchMap(() => {
    const clone: HttpRequest<any> = this.addToken(req, this._auth.getToken());
    return next.handle(clone);
})).catch(error => {
  if ( error.error === 'invalid_token' ) { // if it fails to refresh the token
    // Redirect to Login, but you could also cache the url
    this.router.navigate(['/login']);
    return Observable.throw('Login expired');

  }
  console.log(error);
  return Observable.throw(error);
});

getNewAccessToken()函數如下所示:

  public getNewAccessToken(): Observable<string>  {
    const headers = new HttpHeaders()
    .set('Content-Type', 'application/x-www-form-urlencoded') // FIXME: Replace Encoded Base64 for a custom version
    .set('Authorization', 'Basic WQQPWEOIRUPOIUQ=');

    const params = new HttpParams().set('grant_type', 'refresh_token');
    const httpOptions = { headers: headers, params: params, withCredentials: true };

    return this.httpClient.post( this.oauthTokenUrl,  new FormData(), httpOptions )
      .map(success => {
        this.storeToken(success['access_token']);
      })
      .catch(this.handleError);
  }

storeToken函數:

  public storeToken(token: string) {
    this.jwtPayload = this.jwtHelper.decodeToken(token);
    localStorage.setItem('token', token);
    this.subjectUser.next( { name: this.jwtPayload.name, email: this.jwtPayload.user_name } );
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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