我已经在Angular拦截器中实现了这个逻辑来拦截所有请求并注入Authorization头 . 它还捕获所有401 Unauthorized响应,在这种情况下尝试首先刷新令牌,然后重试原始请求 .

这工作正常,除了我已经知道哪些请求将是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);
            });
    }
}