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 сервис, когда это должно быть отправлено с каждым вызовом. И улучшить DRY. Но все на фабрике выполняется только однажды, таким образом, access_token должен был бы быть доступным прежде, чем определить фабрику и ее изменение наклона впоследствии.

Существует ли способ поместить динамично обновленный параметр запроса в сервис?

62
задан 24 June 2012 в 13:26

5 ответов

Другое решение состояло бы в том, чтобы использовать resource.bind (additionalParamDefaults), тот возврат новый экземпляр ресурса, связанного с дополнительными параметрами

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

, функция access_token будет вызвана каждый раз, когда любое действие с ресурсом называют.

3
ответ дан 31 October 2019 в 13:43

После Вашего принятого ответа я предложил бы расширить ресурс для установки маркера с объектом 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;
}]);

Таким образом нет никакой потребности импортировать TokenHandler каждый раз, когда Вы хотите использовать объект Todo, и можно использовать:

todo.setToken(theNewToken);

Другое изменение, которое я сделал бы, состоит в том, чтобы позволить действия по умолчанию, если они пусты в wrapActions:

if (!actions || actions.length === 0) {
  actions = [];
  for (i in resource) {
    if (i !== 'bind') {
      actions.push(i);
    }
  }
}
1
ответ дан 31 October 2019 в 13:43

Иначе должен использовать перехватчик 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');
});
34
ответ дан 31 October 2019 в 13:43

Я должен был иметь дело с этой проблемой также. Я не думаю, является ли это изящное решение, но это работает и существует 2 строки кода:

я предполагаю, что Вы получаете свой маркер от Вашего сервера после аутентификации в SessionService, например. Затем назовите этот вид метода:

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

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

После этого все Ваши запросы от $resource и $http будут иметь маркер в своем заголовке.

5
ответ дан 31 October 2019 в 13:43

Мне действительно нравится этот подход:

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';
21
ответ дан 31 October 2019 в 13:43

Другие вопросы по тегам:

Похожие вопросы: