【问题标题】:Handle redirects in angularjs $http在 angularjs $http 中处理重定向
【发布时间】:2015-06-10 17:32:58
【问题描述】:

我在我的应用程序中使用了 angularjs http 服务,我在 website 中注意到了这一点:

如果 AJAX 调用成功(服务器在 200 和 209),传递给 success() 函数的函数是 执行。如果 AJAX 调用失败(除 重定向),传递给error()方法的函数被执行。

显然,重定向状态代码既不是成功的一部分,也不是错误回调的一部分。那么我们将如何处理重定向呢?

这就是我的脚本所做的,使用 http get 从服务器获取数据。如果会话过期,服务器返回302 状态码。我应该捕获该状态代码,然后将页面重定向到登录。

app.controller('GraphController', function($scope, $http, localStorageService, $interval) {
        $scope.GraphData = [{"key":"in","values":[]},{"key":"out","values":[]}]; 

        $scope.pollStats = function() {
            $http.get('/statistics/getStat').success(function(lastData, status, headers) {              
                if (status==302) {
                    //this doesn't work
                    //window.location=headers('Location');
                    //this doesn't work either
                    window.location.replace(headers('Location'));
                }else if (status==200) {
                    ...processData
                }
            });
        };
});

显然我的脚本无法运行,因为成功回调无法处理重定向。那么我们应该如何处理呢?

【问题讨论】:

  • 我知道这是一个老问题,但我必须问。您是否尝试实施 OAuth2 重定向?如果是这样,这不是正确的方法,它也不安全。 OAuth2 的部分安全性在于登录是由控制重定向的授权服务器提供的。当您的令牌过期时,您应该只获得 401,然后您知道您需要返回进行身份验证。服务器试图将您重定向到哪里?

标签: angularjs redirect


【解决方案1】:

我也遇到了这个问题,试图找到一种很好的方法来实现第一次登录时提示用户更改密码。

我解决这个问题的方法是让服务器返回一个(非官方的)210 状态代码和一个位置标头,其中包含 UI-Router 的状态提供程序所需的信息。在前面的控制器中我添加了:

if (data.status == 210) {
  var location = data.headers().location;
  $state.go(location);
} else {
  $state.go("user", {name: data.data.fullName, userId: data.data.userId});
}

【讨论】:

    【解决方案2】:

    我认为登录重定向有比http拦截器更好的方法,因为它解析请求响应,如果另一个页面有请求的字符串,就会发生错误。

    我建议在您的服务中包装 $http 方法,并在发出请求之前检查用户是否已登录:

    app.service('httpWrapper', ['$http','requestLogin',function($http,requestLogin){
      var httpWrapper = {};
    
      // You can add methods for put, post
      httpWrapper.get = function(url){
        // Before making the request, check with a request if the user is logged
        $http.get(urlLogged).success(function (auth) {
            if(!auth.logged){
                // Show login widget
                requestLogin.show();
            }
        }).error(function(){
    
        });        
        return $http.get(url);
      }
    
      return httpWrapper;
    }]);
    

    然后在您的其他服务中使用 httpWrapper 代替 $http:

    app.service('otherService', ['httpWrapper',function(httpWrapper){
      httpWrapper.get(url);
    }]);
    

    这里是 requestLogin 的服务:

    app.service('requestLogin', ['$rootScope',function($rootScope){
      var requestLogin = {};
    
      $rootScope.showlogin = false;
    
      requestLogin.show = function(){
        $rootScope.showlogin = true;
      }
    
      requestLogin.hide = function(){
        $rootScope.showlogin = false;
      }    
      return requestLogin;
    }]);
    

    然后,在你看来:

    <div ng-show="showlogin == true">
      Please log-in...
    </div>
    

    【讨论】:

      【解决方案3】:

      请注意,这是针对我的项目的。

      目标:捕获 302 状态代码并重定向页面(在我的情况下登录)。

      结果:在 firebug 中,我可以看到响应代码是 302,但后来我发现 angularjs 通过简单地打印状态值(response.status)返回 200。所以一开始你会认为你是绝望的。但就我而言,我所做的是获取数据(response.data),查找只能在我的登录页面中找到的字符串。然后就是这样。问题解决了:D

      这个想法是在这里接受的。

      这是代码

      app.factory('redirectInterceptor', function($q,$location,$window){
          return  {
              'response':function(response){
              if (typeof response.data === 'string' && response.data.indexOf("My Login Page")>-1) {
                  console.log("LOGIN!!");
                  console.log(response.data);
                  $window.location.href = "/login.html";
                  return $q.reject(response);
              }else{
                  return response;
              }
              }
          }
      
          });
      
          app.config(['$httpProvider',function($httpProvider) {
              $httpProvider.interceptors.push('redirectInterceptor');
          }]); 
      

      【讨论】:

      • 在 angularjs 1.3 中拦截 302 状态码我必须使用 'responseError' 拦截器
      • 只是一个帮助人们理解这一点的注释——需要这种技术不是因为 Angular 正在做任何事情,而是因为 XHR 浏览器 api。重定向由浏览器处理,对 Javascript 层完全不可见; XHR 请求的标头、正文和状态始终是 final 响应的标头、正文和状态。因此,您只能知道您是否被可用于评估响应内容的先验知识重定向。解决此问题的一种技术是让您的服务器 API 在已知属于重定向链的响应中明确包含重定向信息。
      • 小心。这可能是您的应用程序中的一个安全漏洞。由于$http 用于获取各种数据,如果任何其他请求数据包含文本My Login Page,则您的应用程序开始出现错误
      • 如果我在标头中将身份验证令牌发送到我的服务并重定向到第 3 方,如果我得到正确的结果,则重定向会自动继承我添加到原始请求的标头。如果我做对了,这可能是一个安全漏洞@分号
      猜你喜欢
      • 2017-06-12
      • 2014-12-02
      • 1970-01-01
      • 2020-02-20
      • 2018-07-15
      • 2019-08-26
      • 1970-01-01
      • 2014-07-31
      • 2020-08-04
      相关资源
      最近更新 更多