【问题标题】:How to update headers in $resource when routing to a new state路由到新状态时如何更新 $resource 中的标头
【发布时间】:2017-06-24 12:11:27
【问题描述】:

我正在尝试在这个项目中实现 JWT 令牌。为此,我在$resource 中使用了授权标头,就像这样。

当我以 UI 状态“A”登录时,在登录后,我将令牌放入 localStorage 中

$localStorage.token = data.token;

当我转到页面的 UI 状态“B”时,它使用以下服务并发送没有令牌的请求。但是在刷新页面时,它会使用令牌发送相同的请求。

angular.module('BlurAdmin')
    .factory('valueService', ['Token','$localStorage','$resource', 'endpoint', function(Token,$localStorage, $resource, endpoint) {
        return {
            getValues: $resource(endpoint + '/admin/getvalues', null, {
                'get': {
                    method: 'GET',
                    headers:{'Authorization':'Bearer '+$localStorage.token}
                 }
            }),
        }   
}]);

我认为该服务最初会存储 $localStorage.token 值,即使状态发生变化也会使用它。但是当页面重新加载时,它会再次获得$localStorage.token 值。

如何在每次 UI 状态更改时强制此服务获取 $localStorage.token 值?

提前致谢!

【问题讨论】:

  • 它正在处理 get 请求,但是当我发送 post 请求时,我收到它不是构造函数的错误。我现在标记为正确的一个解决方案需要更少的工作,因为我不需要在我的控制器中进行更改,而只需更改服务中的一行。希望你能理解。你的也是正确的,所以我也赞成:)
  • 嗯,将代码更改为method: 'POST' 在这里效果很好。该解决方案独立于您使用的HTTP-Method。两种解决方案(另一个答案)都工作得很好。我了解其他解决方案与您之前尝试过的解决方案更相同。请记住,其他解决方案仅适用于设置标题。例如method: $localStorage.method 将不起作用。干杯

标签: angularjs angular-ui-router jwt angular-services angular-local-storage


【解决方案1】:

要让资源计算每个 XHR GET 操作的标头值,请提供函数而不是值:

angular.module('BlurAdmin')
    .factory('valueService', ['Token','$localStorage','$resource', 'endpoint', function(Token,$localStorage, $resource, endpoint) {
        return {
            getValues: $resource(endpoint + '/admin/getvalues', null, {
                'get': {
                    method: 'GET',
                    //headers:{'Authorization':'Bearer '+$localStorage.token}
                    headers:
                       {'Authorization':
                            function () {
                               return 'Bearer '+$localStorage.token;
                            }
                       }
                 }
            }),
        }   
}]);

提供值时,会在创建资源时计算标头值。提供函数时,每次调用资源get 方法时都会计算头部值。

  • headers – {Object} – 字符串映射或返回字符串的函数表示要发送到服务器的 HTTP 标头。如果函数的返回值为 null,则不会发送标头。函数接受配置对象作为参数。

    -- AngularJS $http Service API Reference - Usage

【讨论】:

    【解决方案2】:

    您的问题是资源定义是在创建时提供的(在您保存令牌之前)。要避免这种行为,只需创建一个包装函数并将您的令牌解析到其中。

    angular.module('BlurAdmin')
        .factory('valueService', ['Token','$localStorage','$resource', 'endpoint', function(Token,$localStorage, $resource, endpoint) {
            return function (token) {
                return $resource(endpoint + '/admin/getvalues', {}, {
                    get: {
                        method: 'GET',
                        headers:{'Authorization':'Bearer ' + token}
                    }
                })
            }
        }]);
    

    像这样调用你的工厂函数:

    valueService($localStorage.token).get(function (result) {
        console.log(result);
    }, function (error) {
        console.log(result);
    });
    

    【讨论】:

    • HI lin,最初我是这样称呼它的 var getValues = new valueService().getValues(); getValues.$get({},function(data){ console.log(data); if (data.status == "success") { $scope.values = data.response; } else { $scope.notify = {消息:data.statusMessage,状态:data.status,类型:“危险”}}});
    • 我现在应该对此做些什么改变?
    • 添加您在line 3 中看到的包装函数,并像valueService($localStorage.token).getValues)... 一样将$localStorage.token 解析到其中
    • 是的,我做到了。但是现在如何调用服务的 $get 函数呢?
    • var getValues = new valueService($localStorage.token).getValues(); getValues.$get({},function(data){ console.log(data); })
    【解决方案3】:

    如果您在使用多个 API 调用的标头时,最好将其添加到公共位置,而不是在每个 API 中添加它

    请参考:拦截器https://docs.angularjs.org/api/ng/service/$http

    angular.module('utimf.services', ['ngResource', 'ng.deviceDetector'])
    .factory('UtimfHttpIntercepter', UtimfHttpIntercepter)
    
    UtimfHttpIntercepter.$inject = ['$q', '$localStorage'];
    function UtimfHttpIntercepter($q, $localStorage) {
    var authFactory = {};
    
    var _request = function (config) {
        config.headers = config.headers || {}; // change/add hearders
        config.data = config.data || {}; // change/add post data
        config.params = config.params || {}; //change/add querystring params
        config.headers['Authorization'] = 'Bearer '+$localStorage.token; // New headers are added here          
    
        return config || $q.when(config);
    }
    
    var _requestError = function (rejection) {
        // handle if there is a request error
        return $q.reject(rejection);
    }
    
    var _response = function(response){
        // handle your response
        return response || $q.when(response);
    }
    
    var _responseError = function (rejection) {
        // handle if there is a request error
        return $q.reject(rejection);
    }
    
    authFactory.request = _request;
    authFactory.requestError = _requestError;
    authFactory.response = _response;
    authFactory.responseError = _responseError;
    return authFactory;
    }
    

    并在您的配置中添加$httpProvider.interceptors.push('UtimfHttpIntercepter');

    【讨论】:

    • 这如何解决用户问题?这是一个“如何重构”的答案。
    猜你喜欢
    • 2021-04-26
    • 2022-01-18
    • 2020-09-05
    • 2016-10-21
    • 1970-01-01
    • 2018-01-05
    • 2020-01-25
    • 1970-01-01
    • 2022-11-29
    相关资源
    最近更新 更多