Обработка CSRF / XSRF токенов с угловым фронтендом и бэкендом Drupal 7


Я в процессе создания нового интерфейса AngularJS для веб-сайта Drupal 7. Это использование модуля служб с сеансовой аутентификацией, в двух доменах, использующих CORS. Я могу аутентифицироваться с помощью Drupal, извлекать объект пользователя и данные сеанса, а затем получать маркер CSRF из модуля служб. С чем у меня возникли проблемы, так это с настройкой всего этого в заголовке, чтобы последующие запросы были аутентифицированы. Я понимаю общую концепцию, но я новичок в обоих случаях. AngularJS и предотвращение атак CSRF.

Из того, что я собрал, читая об этой настройке с AngularJS и RubyOnRails, могут быть несоответствия между платформами относительно того, как маркер называется и как он обрабатывается. Существует также ряд предложений о том, как установить этот маркер в заголовке. Однако мне трудно найти убедительный пример того, как заставить эти платформы говорить на одном языке.

Единственное, что я делаю с моим $httpProvider в приложении.js-это:

delete $httpProvider.defaults.headers.common['X-Requested-With'];

Контроллер входа в систему, в контроллере.js:

  .controller('LoginCtrl', ['$scope', '$http', '$cookies', 'SessionService', function($scope, $http, $cookies, SessionService) {
    $scope.login = function(user) {
        //set login url and variables
        var url = 'http://mywebsite.com/service/default/user/login.json';
        var postDataString = 'name=' + encodeURIComponent(user.username) + '&pass=' + encodeURIComponent(user.password);

        $http({
            method: 'POST',
            url: url,
            data : postDataString,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).success(function (data, status, headers, config) {
            var sessId = data.sessid;
            var sessName = data.session_name;
            $cookies[sessName] = sessId;

            var xsrfUrl = 'http://mywebsite.com/services/session/token';
            $http({
                method: 'GET',
                url: xsrfUrl
            }).success(function (data, status, headers, config) {
                $cookies["XSRF-TOKEN"] = data;
                SessionService.setUserAuthenticated(true);
            }).error(function (data, status, headers, config) {
                console.log('error loading xsrf/csrf');
            });
        }).error(function (data, status, headers, config) {
            if(data) {
                console.log(data);
                var msgText = data.join("n");
                alert(msgText);
            } else {
                alert('Unable to login');
            }
        });
      };
4 4

4 ответа:

Решение связано с тем, как файлы cookie должны быть установлены и затем переданы через последующие запросы. Попытки установить их вручную не увенчались успехом, но решение оказалось проще, чем я ожидал. Каждый вызов $http должен задать следующие параметры:

withCredentials: true
Еще одно изменение, которое я сделал, заключалось в использовании термина CSRF вместо XSRF, чтобы соответствовать Drupal. Я не использовать какие-либо встроенные функции в AngularJS от CSRF атак.
        addItem: function(data)
        {
            return $http.post('api/programs/'+$stateParams.id+'/workouts', {item:data},{
                headers:
                {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                    'X-CSRF-Token': $('meta[name="xxtkn"]').attr('content')

                }
            });
        }

С тех пор как прошел год этой темы! не уверен, что все еще сталкиваюсь с той же проблемой, но для тех, кто приходит искать ответы вот как я справляюсь с этим! Обратите внимание на заголовки{} Часть i определите новый заголовок и назовите его X-CSRF-Token и захватите значение из DOM (serverside) сгенерированного html или php. Это не хорошая практика, чтобы также просить CSRF токен с сервера.Потому что атакующий мог каким-то образом запросить и это. Так как вы сохраняете его как печенье. Злоумышленник может украсть печенье! Нет необходимости сохранять его в печенье! отправьте маркер с заголовком и прочитайте его на стороне сервера, чтобы соответствовать ему!

И для мультитаб одного и того же выпуска страницы. Я использую один и тот же токен на протяжении всей сессии. Регенерируйте только при входе, выходе из системы и изменении основных настроек сайта или пользователя.

Есть отличная библиотека callse ng-drupal-7-services. Если вы используете это в вашем проекте, он решает аутентификацию / повторную аутентификацию и создание файла / узла aut коробки, и вы можете сосредоточиться на важных вещах в вашем проекте.

Итак, аутентификация там решается следующим образом:

function login(loginData) {
  //UserResource ahndles all requeste of the services 3.x user resource.
  return UserResource
  .login(loginData)
  .success(function (responseData, status, headers, config) {
    setAuthenticationHeaders(responseData.token);

    setLastConnectTime(Date.now());
    setConnectionState((responseData.user.uid === 0)?false:true)
    setCookies(responseData.sessid, responseData.session_name);
    setCurrentUser(responseData.user);

    AuthenticationChannel.pubLoginConfirmed(responseData);
  })
  .error(function (responseError, status, headers, config) {
    AuthenticationChannel.pubLoginFailed(responseError);
  });

};

(function() {
'use strict';


	 

AuthenticationHttpInterceptor.$inject = [ '$injector'];

function AuthenticationHttpInterceptor($injector) {
	
  	
    var intercepter = {
    	request 	: doRequestCongiguration,
    };
    
    return intercepter;

    function doRequestCongiguration (config) {
        var tokenHeaders = null;
 
        // Need to manually retrieve dependencies with $injector.invoke
        // because Authentication depends on $http, which doesn't exist during the
        // configuration phase (when we are setting up interceptors).
        // Using $injector.invoke ensures that we are provided with the
        // dependencies after they have been created.
        $injector.invoke(['AuthenticationService', function (AuthenticationService) {
            tokenHeaders = AuthenticationService.getAuthenticationHeaders();
            
        }]);

        //add headers_______________________
        
        //add Authorisation and X-CSRF-TOKEN if given
        if (tokenHeaders) {
            angular.extend(config.headers, tokenHeaders);
        }
        
        //add flags_________________________________________________
        
        //add withCredentials to every request
        //needed because we send cookies in our request headers
        config.withCredentials = true;

        return config;
    };
	

Существует также своего рода кухонная раковина для этого проекта здесь: Drupal-API-Explorer

Да, каждая платформа имеет свое собственное соглашение в именовании своих токенов.

Вот небольшая библиотека, собранная вместе в надежде сделать ее простой в использовании с различными платформами. Это позволит вам использовать имена наборов и может использоваться во всех запросах. Он также работает для междоменных запросов.

Https://github.com/pasupulaphani/angular-csrf-cross-domain