AngularJS:如何用$资源请求发送授权令牌?

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

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

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

我有一个存储auth令牌的服务:

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在定义工厂之前必须可用,并且之后不能更改。

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


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

正如您期望的那样,后一种方法实际上会将操作包装为在每个请求中包含身份验证令牌并返回已修改的资源。 所以让我们来看看这个代码:

.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()方法。 正如Andy Joslin所建议的那样,这种新方法将_query()包装为提供通过该操作发送的每个请求的身份验证令牌。

这种方法的好处在于,我们仍然可以使用每个angularjs资源(get,query,save等)附带的预定义操作,而无需重新定义它们。 在其余的代码中(例如在控制器中),我们可以使用默认的动作名称。


另一种方法是使用HTTP拦截器,用当前的OAuth令牌替换“神奇”授权标头。 下面的代码是特定于OAuth的,但补救措施对读者来说是一个简单的练习。

// Injects an HTTP interceptor that replaces a "Bearer" authorization header
// with the current Bearer token.
module.factory('oauthHttpInterceptor', function (OAuth) {
  return {
    request: function (config) {
      // This is just example logic, you could check the URL (for example)
      if (config.headers.Authorization === 'Bearer') {
        config.headers.Authorization = 'Bearer ' + btoa(OAuth.accessToken);
      }
      return config;
    }
  };
});

module.config(function ($httpProvider) {
  $httpProvider.interceptors.push('oauthHttpInterceptor');
});

我非常喜欢这种方法:

http://blog.brunoscopelliti.com/authentication-to-a-restful-web-service-in-an-angularjs-web-app

其中令牌总是在请求头中自动发送而不需要包装器。

// Define a new http header
$http.defaults.headers.common['auth-token'] = 'C3PO R2D2';
链接地址: http://www.djcxy.com/p/89547.html

上一篇: AngularJS: How to send auth token with $resource requests?

下一篇: image with an rgba background