javascript - AngularJS:如何使用 $resource 请求发送身份验证 token ?

标签 javascript authentication angularjs

我想在从我的 API 请求资源时发送一个授权 token 。

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

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

我有一个存储授权 token 的服务:

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

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

  return tokenHandler;
});

我想从 tokenHandler.get 发送 token 以及通过 Todo 服务发送的每个请求。我能够通过将其放入特定操作的调用中来发送它。例如,这有效:

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

但我更愿意将 access_token 定义为 Todo 服务中的参数,因为它必须随每次调用一起发送。并改善DRY。 但是工厂中的所有内容都只执行一次,因此 access_token 必须在定义工厂之前可用并且之后不能更改。

有没有办法在服务中放置一个动态更新的请求参数?

最佳答案

感谢安迪·乔斯林。我选择了他包装资源操作的想法。资源的服务现在看起来像这样:

.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() 方法的返回值覆盖,该方法将资源和一组操作作为参数。

正如您所期望的那样,后一种方法实际上包装了操作以在每个请求中包含身份验证 token 并返回修改后的资源。那么让我们看一下它的代码:

.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 所建议的那样,为通过该操作发送的每个请求提供身份验证 token 。

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

关于javascript - AngularJS:如何使用 $resource 请求发送身份验证 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11176330/

相关文章:

javascript - 从 javascript 设置 html 值?

javascript - 创建自定义 HTML 元素的新实例

javascript - 为什么函数内部的这个变量可以读取函数语句下的全局变量?

php 和服务器端 javascript

mysql - 为MariaDB根用户启用密码和unix_socket身份验证?

angularjs - 如何在 AngularJS 2 中实现 ngClass (AngularJS 1.x) 的功能?

javascript - 错误 : $injector:modulerr Module Error - chart. js

authentication - 通过私有(private)账户从 Netflix 拉取数据

ios - 使用自定义后端进行 Firebase 身份验证

javascript - 图像作为单选按钮