AngularJS : $ resource 요청으로 인증 토큰을 보내는 방법은 무엇입니까?
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()} );
그러나 Todo
모든 호출과 함께 전송되어야 하므로 access_token을 서비스 의 매개 변수로 정의하는 것을 선호합니다 . 그리고 DRY를 개선합니다. 그러나 팩토리의 모든 것은 한 번만 실행되므로 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()
메서드를 덮어 씁니다 . 이 새로운 메서드 _query()
는 Andy Joslin이 제안한대로을 래핑 하여 해당 작업을 통해 전송되는 모든 요청에 인증 토큰을 제공합니다.
이 접근 방식의 좋은 점은 모든 angularjs 리소스 (가져 오기, 쿼리, 저장 등)와 함께 제공되는 사전 정의 된 작업을 재정의하지 않고도 사용할 수 있다는 것입니다. 나머지 코드 (예 : 컨트롤러 내)에서는 기본 작업 이름을 사용할 수 있습니다.
또 다른 방법은 "마법의"Authorization 헤더를 현재 OAuth 토큰으로 대체하는 HTTP 인터셉터를 사용하는 것입니다. 아래 코드는 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';
그것에 대한 래퍼 함수를 만들 수 있습니다.
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;
})
나는이 문제도 다루어야했다. 나는 그것이 우아한 해결책이라고 생각하지 않지만 작동하고 두 줄의 코드가 있습니다.
예를 들어 SessionService에서 인증 한 후 서버에서 토큰을 얻는다고 가정합니다. 그런 다음 이러한 종류의 메서드를 호출합니다.
angular.module('xxx.sessionService', ['ngResource']).
factory('SessionService', function( $http, $rootScope) {
//...
function setHttpProviderCommonHeaderToken(token){
$http.defaults.headers.common['X-AUTH-TOKEN'] = token;
}
});
그 후 $ resource 및 $ http의 모든 요청에는 헤더에 토큰이 있습니다.
Another solution would be to use resource.bind(additionalParamDefaults), that return a new instance of the resource bound with additional parameters
var myResource = $resource(url, {id: '@_id'});
var myResourceProtectedByToken = myResource.bind({ access_token : function(){
return tokenHandler.get();
}});
return myResourceProtectedByToken;
The access_token function will be called every time any of the action on the resource is called.
I might be misunderstanding all of your question (feel free to correct me :) ) but to specifically address adding the access_token
for every request, have you tried injecting the TokenHandler
module into the Todo
module?
// app
var app = angular.module('app', ['ngResource']);
// token handler
app.factory('TokenHandler', function() { /* ... */ });
// inject the TokenHandler
app.factory('Todo', function($resource, TokenHandler) {
// get the token
var token = TokenHandler.get();
// and add it as a default param
return $resource('http://localhost:port/todos.json', {
port: ':3001',
access_token : token
});
})
You can call Todo.query()
and it will append ?token=none
to your URL. Or if you prefer to add a token placeholder you can of course do that too:
http://localhost:port/todos.json/:token
Hope this helps :)
Following your accepted answer, I would propose to extend the resource in order to set the token with the Todo object:
.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"] );
resource.prototype.setToken = function setTodoToken(newToken) {
tokenHandler.set(newToken);
};
return resource;
}]);
In that way there is no need to import the TokenHandler each time you want to use the Todo object and you can use:
todo.setToken(theNewToken);
Another change I would do is to allow default actions if they are empty in wrapActions
:
if (!actions || actions.length === 0) {
actions = [];
for (i in resource) {
if (i !== 'bind') {
actions.push(i);
}
}
}
참고URL : https://stackoverflow.com/questions/11176330/angularjs-how-to-send-auth-token-with-resource-requests
'IT박스' 카테고리의 다른 글
문자열에서 "¼"및 "½"과 같은 모든 분수 기호 제거 (0) | 2020.11.28 |
---|---|
입력 필드가있는 메시지 상자 (0) | 2020.11.27 |
open ()을 위해 다른 디렉토리에있는 파일의 전체 경로를 전달해야합니까? (0) | 2020.11.27 |
New-WebServiceProxy를 통해 웹 서비스에 추가 HTTP 헤더를 보낼 수 있습니까? (0) | 2020.11.27 |
jquery 확장 대 각도 확장 (0) | 2020.11.27 |