AngularJS - http interceptor - resend all request after token refresh

前端 未结 2 1646
谎友^
谎友^ 2020-12-08 10:49

I have an angular app which sometimes does multiple $http.get requests per state. The app usees JWT for user auth with refresh tokens. The API server sends 401

2条回答
  •  半阙折子戏
    2020-12-08 11:11

    Your interceptor needs to keep track of whether or not it has an authentication request "in flight". It can do this by keeping a reference to the promise returned by the authentication request. If there is a request in flight and you get another 401, just use that cached promise instead of initiating a new request. Also, you should consider adding logic to account for the case when '/api/auth/refresh' itself returns a 401.

    app.factory('AuthInterceptor', function($q, $injector, RESOURCE_URL, API_BASE, authService) {
        var inflightAuthRequest = null;
        return {
            request: function(config) {
                config.headers = config.headers || {};
                if (authService.getAccessToken()) {
                    if (config.url.substring(0, RESOURCE_URL.length) !== RESOURCE_URL) {
                        config.headers.Authorization = 'Bearer ' + authService.getAccessToken();
                    }
                }
                return config;
            },
            responseError: function(response) {
                switch (response.status) {
                    case 401:
                        var deferred = $q.defer();
                        if(!inflightAuthRequest) {
                            inflightAuthRequest = $injector.get("$http").post(API_BASE + '/api/auth/refresh', {refreshtoken: authService.getRefreshToken()});
                        }
                        inflightAuthRequest.then(function(r) {
                            inflightAuthRequest = null;
                            if (r.data.data.accesstoken && r.data.data.refreshtoken && r.data.data.expiresin) {
                                authService.setAccessToken(r.data.data.accesstoken);
                                authService.setRefreshToken(r.data.data.refreshtoken);
                                authService.setExpiresIn(r.data.data.expiresin);
                                $injector.get("$http")(response.config).then(function(resp) {
                                    deferred.resolve(resp);
                                },function(resp) {
                                    deferred.reject();
                                });
                            } else {
                                deferred.reject();
                            }
                        }, function(response) {
                            inflightAuthRequest = null;
                            deferred.reject();
                            authService.clear();
                            $injector.get("$state").go('guest.login');
                            return;
                        });
                        return deferred.promise;
                        break;
                    default:
                        authService.clear();
                        $injector.get("$state").go('guest.login');
                        break;
                }
                return response || $q.when(response);
            }
        };
    });
    

提交回复
热议问题