Nil*_*ste 62 javascript authentication angularjs
我想在从API请求资源时发送身份验证令牌.
我确实使用$ resource实现了一项服务:
factory('Todo', ['$resource', function($resource) {
return $resource('http://localhost:port/todos.json', {port:":3001"} , {
query: {method: 'GET', isArray: true}
});
}])
Run Code Online (Sandbox Code Playgroud)
我有一个存储身份验证令牌的服务:
factory('TokenHandler', function() {
var tokenHandler = {};
var token = "none";
tokenHandler.set = function( newToken ) {
token = newToken;
};
tokenHandler.get = function() {
return token;
};
return tokenHandler;
});
Run Code Online (Sandbox Code Playgroud)
我想tokenHandler.get通过Todo服务发送的每个请求发送令牌.我能够通过将其置于特定动作的调用中来发送它.例如,这有效:
Todo.query( {access_token : tokenHandler.get()} );
Run Code Online (Sandbox Code Playgroud)
但我更愿意将access_token定义为Todo服务中的参数,因为它必须随每次调用一起发送.并改善干旱.但是工厂中的所有东西只执行一次,因此在定义工厂之前必须提供access_token,之后它不能更改.
有没有办法在服务中放置动态更新的请求参数?
Nil*_*ste 60
感谢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;
}])
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,资源首先是通常的定义方式.在我的例子,这包括所谓的自定义操作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;
});
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该wrapActions()方法从其参数创建资源的副本,并在actions数组中循环tokenWrapper()以为每个操作调用另一个函数.最后,它返回资源的修改副本.
该tokenWrapper方法首先创建预先存在的资源动作的副本.此副本具有尾随下划线.因此query()变得_query().然后,新方法将覆盖原始query()方法._query()正如Andy Joslin所建议的那样,这个新方法包含了通过该动作发送的每个请求的auth令牌.
这种方法的好处是,我们仍然可以使用每个angularjs资源(获取,查询,保存等)附带的预定义操作,而无需重新定义它们.在其余代码中(例如在控制器内),我们可以使用默认操作名称.
Ben*_*ing 34
另一种方法是使用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');
});
Run Code Online (Sandbox Code Playgroud)
ric*_*cit 21
我真的很喜欢这种方法:
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';
Run Code Online (Sandbox Code Playgroud)
您可以为它创建包装函数.
app.factory('Todo', function($resource, TokenHandler) {
var res= $resource('http://localhost:port/todos.json', {
port: ':3001',
}, {
_query: {method: 'GET', isArray: true}
});
res.query = function(data, success, error) {
//We put a {} on the first parameter of extend so it won't edit data
return res._query(
angular.extend({}, data || {}, {access_token: TokenHandler.get()}),
success,
error
);
};
return res;
})
Run Code Online (Sandbox Code Playgroud)
我也必须处理这个问题.我不认为它是否是一个优雅的解决方案,但它的工作原理有两行代码:
我想您在SessionService中进行身份验证后从服务器获取令牌.然后,调用这种方法:
angular.module('xxx.sessionService', ['ngResource']).
factory('SessionService', function( $http, $rootScope) {
//...
function setHttpProviderCommonHeaderToken(token){
$http.defaults.headers.common['X-AUTH-TOKEN'] = token;
}
});
Run Code Online (Sandbox Code Playgroud)
之后,来自$ resource和$ http的所有请求都会在其标题中包含令牌.
| 归档时间: |
|
| 查看次数: |
54985 次 |
| 最近记录: |