sourcecode

AngularJS: $resource 요청과 함께 인증 토큰을 보내려면 어떻게 해야 합니까?

codebag 2023. 3. 19. 18:08
반응형

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()} );

단, access_token을 파라미터로 정의하고 싶습니다.Todo모든 콜에 대해 전송해야 하기 때문에 서비스를 제공합니다.그리고 드라이를 개선합니다.단, 공장 내의 모든 것은 1회만 실행되므로 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()리소스 및 작업 배열을 매개 변수로 사용하는 메서드입니다.

후자의 메서드는 실제로 모든 요구에 인증 토큰을 포함하는 액션을 랩하고 변경된 리소스를 반환합니다.그럼 그 코드를 보겠습니다.

.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()method는 해당 파라미터에서 리소스 복사본을 생성하여 루프를 수행합니다.actions다른 함수를 호출하는 배열tokenWrapper()모든 액션에 대해마지막으로 수정된 리소스 복사본을 반환합니다.

tokenWrappermethod는 우선 기존 자원 액션의 복사본을 만듭니다.이 복사본은 뒤에 밑줄이 있다.그렇게query()된다_query()그 후, 새로운 메서드가 원래의 메서드를 덮어씁니다.query()방법.이 새로운 메서드는 랩됩니다._query()(Andy Joslin에 의해 제안되었듯이) 이 액션을 통해 전송되는 모든 요구와 함께 인증 토큰을 제공합니다.

이 접근방식의 장점은 모든 angularj 자원(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';

래퍼 기능을 만들 수 있습니다.

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;
})

저도 이 문제를 해결해야 했어요.이것이 우아한 솔루션이라고는 생각하지 않지만 효과가 있고 코드 행이 2개 있는 경우:

예를 들어 Session Service에서 인증을 받은 후 서버에서 토큰을 얻을 수 있습니다.그런 다음 다음과 같은 메서드를 호출합니다.

   angular.module('xxx.sessionService', ['ngResource']).
    factory('SessionService', function( $http,  $rootScope) {

         //...
       function setHttpProviderCommonHeaderToken(token){
          $http.defaults.headers.common['X-AUTH-TOKEN'] = token;
       }  
   });

그 후 $resource 및 $http로부터의 모든 요청은 헤더에 토큰이 포함됩니다.

다른 솔루션은 resource.bind(additional Param Defaults)를 사용하여 추가 파라미터로 바인드된 리소스의 새 인스턴스를 반환하는 것입니다.

var myResource = $resource(url, {id: '@_id'});
var myResourceProtectedByToken = myResource.bind({ access_token : function(){
        return tokenHandler.get();
}});
return myResourceProtectedByToken;

access_token 함수는 리소스에 대한 액션이 호출될 때마다 호출됩니다.

가 당신의하고 있는 것 해 주세요으로 말하면, 이 질문의 말씀드리겠습니다.access_token, 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」를해 본 적이 있습니까?TokenHandler 입력하다Todo모??

// 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
    });
})

요.Todo.query() 붙을 예요.?token=none토큰 플레이스 홀더를 추가하려면 물론 다음을 수행합니다.

http://localhost:port/todos.json/:token

이것이 도움이 되기를 바랍니다:)

수락하신 답변에 따라 Todo 오브젝트로 토큰을 설정하기 위해 리소스를 확장할 것을 제안합니다.

.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;
}]);

이렇게 하면 ToDo 객체를 사용할 때마다 TokenHandler를 Import할 필요가 없으며 다음을 사용할 수 있습니다.

todo.setToken(theNewToken);

의 변경은 디폴트액션이 빈 디폴트액션을 입니다.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

반응형