一尘不染

AngularJS:如何使用$ resource请求发送身份验证令牌?

angularjs

我想从我的API请求资源时发送身份验证令牌。

我确实使用$ resource实现了服务:

factory('Todo', ['$resource', function($resource) {
 return $resource('http://localhost:port/todos.json', {port:":3001"} , {
   query: {method: 'GET', isArray: true}
 });
}])

我有一个存储身份验证令牌的服务:

factory('TokenHandler', function() {
  var tokenHandler = {};
  var token = "none";

  tokenHandler.set = function( newToken ) {
    token = newToken;
  };
  tokenHandler.get = function() {
    return token;
  };

  return tokenHandler;
});

我想tokenHandler.get通过Todo服务发送的每个请求都发送令牌。通过将其放入特定动作的调用中,我能够发送它。例如,这有效:

Todo.query( {access_token : tokenHandler.get()} );

但是我宁愿将access_token定义为Todo服务中的参数,因为它必须随每个调用一起发送。并提高干度。但是工厂中的所有内容仅执行一次,因此access_token在定义工厂之前必须是可用的,此后不能更改。

有没有办法将动态更新的请求参数放入服务中?


阅读 204

收藏
2020-07-04

共1个答案

一尘不染

感谢Andy Joslin。我选择了他包装资源操作的想法。资源服务现在看起来像这样:

.factory('Todo', ['$resource', 'TokenHandler', function($resource, tokenHandler) {
  var resource = $resource('http://localhost:port/todos/:id', {
    port:":3001",
    id:'@id'
    }, {
      update: {method: 'PUT'}
    });

  resource = tokenHandler.wrapActions( resource, ["query", "update"] );

  return resource;
}])

如您所见,资源首先是按常规方式定义的。在我的示例中,这包括一个名为的自定义操作update。之后,通过返回tokenHandler.wrapAction()方法将资源覆盖,该方法将资源和一系列操作作为参数。

如您所料,后一种方法实际上包装了操作以在每个请求中包括auth令牌,并返回修改后的资源。因此,让我们看一下代码:

.factory('TokenHandler', function() {
  var tokenHandler = {};
  var token = "none";

  tokenHandler.set = function( newToken ) {
    token = newToken;
  };

  tokenHandler.get = function() {
    return token;
  };

  // wrap given actions of a resource to send auth token with every
  // request
  tokenHandler.wrapActions = function( resource, actions ) {
    // copy original resource
    var wrappedResource = resource;
    for (var i=0; i < actions.length; i++) {
      tokenWrapper( wrappedResource, actions[i] );
    };
    // return modified copy of resource
    return wrappedResource;
  };

  // wraps resource action to send request with auth token
  var tokenWrapper = function( resource, action ) {
    // copy original action
    resource['_' + action]  = resource[action];
    // create new action wrapping the original and sending token
    resource[action] = function( data, success, error){
      return resource['_' + action](
        angular.extend({}, data || {}, {access_token: tokenHandler.get()}),
        success,
        error
      );
    };
  };

  return tokenHandler;
});

如您所见,该wrapActions()方法从其参数创建资源的副本,并遍历actions数组tokenWrapper()以为每个操作调用另一个函数。最后,它返回修改后的资源副本。

tokenWrapper方法首先创建一个预先存在的资源操作的副本。该副本下划线。如此query()成为_query()。之后,新方法将覆盖原始query()方法。_query()正如Andy
Joslin所建议的那样,此新方法将包装以为通过该操作发送的每个请求提供auth令牌。

这种方法的好处是,我们仍然可以使用每个angularjs资源(获取,查询,保存等)附带的预定义操作,而不必重新定义它们。在其余代码中(例如在控制器内),我们可以使用默认操作名称。

2020-07-04