Angularjs在应用程序范围内处理401错误

时间:2014-07-23 09:54:14

标签: angularjs access-token http-status-code-401 jwt

我在应用程序范围内处理401错误时遇到了一些麻烦。

其他一些没有真正帮助我的帖子: Angularjs - handling 401's for entire app 401 unauthorized error handling in AngularJS

我必须发送一个身份验证令牌,如果它是在每个请求上定义的,这就是为什么我需要拦截器中的请求部分。

我目前的方法如下:

module.factory('authInterceptor', function ($rootScope, $q, $window, $location) {
  return {
    request: function (config) {
      config.headers = config.headers || {};
      if ($window.sessionStorage.token) {
        config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
      }
      else{
          console.log("authInterceptor: No Token to send")
      }
      return config;
    },
    response: function (response) {
      if (response.status == 401) {
          console.log("No Logged In");
         $location.path('/login');
      }
      return response || $q.when(response);
    },
    responseError: function(rejection){

                var defer = $q.defer();

                if(rejection.status == 401){
                    console.log("401 Rejection");
                    console.dir(rejection);
                }

                defer.reject(rejection);

                return defer.promise;

            }

  };
});

就我的调试而言,如果401在请求之后发生,它将在repsonse函数中处理。这本身就是对原始来电者的承诺。

如果我注释掉$ q.when(响应)并且只返回repsonse则没有变化。

甚至在原始调用者获得.error

之前就会调用响应

任何想法的Thx。希望我不要远离解决方案。

4 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,在我的情况下问题是我在响应中添加了CORS标头作为后置过滤器,这意味着在发出401时它们没有被发送。

不确定您使用的是哪种类型的服务器,但这是适用于我的rails版本(将其更改为 before_filter

before_filter :allow_cors

def allow_cors
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = 'Accept, Cache-Control, Referer, User-Agent, Origin, X-Requested-With, X-Prototype-Version, Content-Type, accept, autho
  headers['Access-Control-Allow-Credentials'] = 'true'
  headers['Access-Control-Request-Method'] = '*'
  headers['Access-Control-Max-Age'] = '1728000'
end

(显然这些是非常宽松的设置,所以请在生产中使用之前调整它们)

他们通过CURL在本地测试请求,我设法找到了这个,所以这可能对你有所帮助:

curl -H "Origin: http://example.com" --verbose http://localhost:3000/

通过这种方式,即使请求未获得授权,您也可以查看是否正确返回了标题。

答案 1 :(得分:0)

你的方法很好。

我认为你不需要“响应”拦截器,只需“请求”注入令牌和“responseError”来处理401响应错误:

return {

    'responseError': function(response) {

        if (response && response.status === 401) {
            //DO WHAT YOU WANT HERE
            console.log("There was a 401 error");
        }

        return $q.reject(response);
    },

    'request': function(config) {
        config.headers = config.headers || {};
        // ADD YOUR HEADER HERE
        return config || $q.when(config);
    }
};

答案 2 :(得分:0)

@frankmt非常感谢!没有足够的代表来支持或评论您的解决方案,无论如何,这正是我错过的。使用Express和CORS,它将是......

//   THE CORS BLOCK HAS TO GO BEFORE THE JWT BLOCK
app.options('*', cors());
app.use(cors());


//protect  routes with JWT - Token based auth
var secret = 'env.SECRET';
var publicPaths = [ '/apply', '/login'];

app.use('/', expressJwt({secret: secret}).unless({path: publicPaths}));

答案 3 :(得分:0)

如果你有堆叠中的Devise;它最有可能失败,因为Warden优先于其他任何事情。标题不会被插入;即使您使用before_action代替after_action

请查看此问题:ttp://stackoverflow.com/questions/11177079/how-to-send-cors-headers-with-devise-if-user-not-authorized-401-response