【问题标题】:Angularjs handling 401 Errors application wideAngularjs 处理应用程序范围内的 401 错误
【发布时间】:2014-09-14 10:47:48
【问题描述】:

我在处理应用程序范围内的 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(response) 并且只返回响应,则没有任何变化。

响应甚至在原始调用者得到 .error 之前就被调用

感谢任何想法。希望我离解决方案不远。

【问题讨论】:

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


    【解决方案1】:

    我遇到了同样的问题,就我而言,问题是我在响应中添加了 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/
    

    这样,即使请求未授权,您也可以查看标头是否正确返回。

    【讨论】:

      【解决方案2】:

      你的方法很好。

      我认为你不需要“response”拦截器,只需要“request”来注入令牌和“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);
          }
      };
      

      【讨论】:

      • 我用 console.log 调试消息尝试了您的示例。但是日志中仍然不会出现消息:authInterceptor: No Token to send cfa.js:11 OPTIONS 10.49.2.160:10000/api/OrderItem 401 (Unauthorized) angular.js:8644 XMLHttpRequest cannot load 10.49.2.160:10000/api/OrderItem。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin '10.49.2.160' 不允许访问。 (index):1 服务器错误
      • 好的,所以您遇到了跨域安全错误,您的 ajax 请求不起作用。与应该工作的拦截器无关。您需要授权CORS服务器端,在SO上进行搜索,您会得到很多相关问题:)
      • 我已经处理了......如果授权成功......只有在这种情况下,当node.js中的授权没有通过时,也会出现CORS错误......//允许来自其他的Cors请求IP 端口 var allowCrossDomain = function(req, res, next) { res.header('Access-Control-Allow-Origin', "*"); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'); //res.header('Access-Control-Allow-Headers', 'Content-Type'); res.header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization');下一个(); } app.use(allowCrossDomain);
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        如果堆栈中有设计;它很可能会失败,因为 Warden 优先于其他任何事情。标题不会被插入;即使您使用 before_action 而不是 after_action。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-28
          • 2018-03-29
          • 2016-07-03
          • 1970-01-01
          • 2019-06-04
          • 1970-01-01
          • 2013-09-11
          • 1970-01-01
          相关资源
          最近更新 更多