4

我正在为 Drupal 7 网站构建新的 AngularJS 前端。这是使用带有基于会话的身份验证的服务模块,跨两个使用 CORS 的域。我能够使用 Drupal 进行身份验证,检索用户对象和会话数据,然后从服务模块获取 CSRF 令牌。我遇到的问题是在标头中设置所有这些,以便对后续请求进行身份验证。我了解整体概念,但对 AngularJS 和防止 CSRF 攻击都是新手。

根据我收集到的关于 AngularJS 和 RubyOnRails 设置的信息,平台之间在令牌命名和处理方式方面可能存在不一致。似乎还有一些关于如何在标题中设置此标记的建议。但是,我很难找到一个可靠的例子来说明如何让这些平台说同一种语言。

我在 app.js 中对 $httpProvider 所做的唯一事情是:

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

登录控制器,在 controller.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

3

该解决方案与如何设置 cookie 以及如何通过后续请求有关。尝试手动设置它们并不顺利,但解决方案比我预期的要简单。每个 $http 调用都需要设置选项:

withCredentials: true

我所做的另一个更改是使用术语 CSRF 而不是 XSRF,以与 Drupal 保持一致。我没有使用任何内置的 AngularJS CSRF 功能。

于 2013-08-16T14:14:40.777 回答
2
        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')

                }
            });
        }

因为这个话题已经一年了!不确定是否仍然遇到同样的问题,但对于那些来这里寻找答案的人来说,这就是我的处理方式!注意 headers{} 部分,我定义了一个新的 header 并将其称为 X-CSRF-Token 并从(服务器端)生成的 html 或 php 的 DOM 中获取值。从服务器请求 csrf 令牌也不是一个好习惯。因为攻击者也可以以某种方式请求它。由于您将其保存为cookie。攻击者可以窃取cookie!无需将其保存在 cookie 中!发送带有标头的令牌并在服务器端读取它以匹配它!

并针对同一页面问题的多选项卡。我在整个会话期间使用相同的令牌。仅在登录、注销和更改主要站点或用户设置时重新生成。

于 2014-05-28T10:39:44.227 回答
2

有一个很棒的库调用ng-drupal-7-services。如果您在项目中使用它,它可以解决盒子的身份验证/重新身份验证和文件/节点创建,您可以专注于项目中的重要内容。

所以身份验证是这样解决的:

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

于 2016-03-12T17:07:07.647 回答
0

是的,每个平台都有自己的代币命名约定。

这是一个放在一起的小库,希望使其易于在不同平台上使用。这将允许您使用集合名称,并且可以在所有请求中使用。它也适用于跨域请求。

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

于 2015-01-05T21:29:54.850 回答