Rest 使用角度前端和Drupal 7后端处理CSRF/XSRF令牌

Rest 使用角度前端和Drupal 7后端处理CSRF/XSRF令牌,rest,drupal,angularjs,drupal-7,csrf,Rest,Drupal,Angularjs,Drupal 7,Csrf,我正在为Drupal7网站构建一个新的AngularJS前端。这是通过使用CORS跨两个域使用基于会话的身份验证的服务模块。我能够使用Drupal进行身份验证,检索用户对象和会话数据,然后从服务模块获取CSRF令牌。我遇到的问题是在报头中设置所有这些,以便对后续请求进行身份验证。我了解整体概念,但对AngularJS和防止CSRF攻击都是新手 从我收集的关于AngularJS和RubyOnRails的设置的资料来看,平台之间可能存在关于令牌名称和处理方式的不一致。对于如何在标头中设置此令牌,似乎

我正在为Drupal7网站构建一个新的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');
            }
        });
      };

解决方案涉及如何设置cookie,然后通过后续请求传递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')

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

对于同一页面问题的multitab。我在整个过程中使用相同的令牌。
仅在登录、注销和更改主要站点或用户设置时重新生成。

是的,每个平台在命名令牌时都有自己的约定

下面是一个小的库,希望它能方便地与不同的平台一起使用。这将允许您使用集合名称,并且可以在所有请求中使用。它也适用于跨域请求


有一个很棒的图书馆callse。如果您在项目中使用此功能,它将解决身份验证/重新身份验证和文件/节点创建问题,并且您可以在项目中讨论重要的内容

因此,身份验证是这样解决的:

函数登录(loginData){
//UserResource处理服务3.x用户资源的所有请求。
返回用户资源
.login(登录数据)
.success(函数(响应数据、状态、标题、配置){
setAuthenticationHeaders(responseData.token);
setLastConnectTime(Date.now());
setConnectionState((responseData.user.uid==0)?false:true
setCookies(responseData.sessiond、responseData.session_name);
setCurrentUser(responseData.user);
AuthenticationChannel.PubLogin已确认(responseData);
})
.error(函数(响应错误、状态、标题、配置){
AuthenticationChannel.pubLoginFailed(responseError);
});
};
(功能(){
"严格使用",;
AuthenticationHttpInterceptor.$inject=['$injector'];
函数身份验证HttpInterceptor($injector){
var拦截器={
请求:DoRequestConfiguration,
};
返回拦截器;
函数DoRequestConfiguration(配置){
var-tokenHeaders=null;
//需要使用$injector.invoke手动检索依赖项
//因为身份验证依赖于$http,而$http在验证过程中不存在
//配置阶段(当我们设置拦截器时)。
//使用$injector.invoke可确保向我们提供
//在创建依赖项之后。
$injector.invoke(['AuthenticationService',函数(AuthenticationService){
tokenHeaders=AuthenticationService.getAuthenticationHeaders();
}]);
//添加标题_______________________
//添加授权和X-CSRF-TOKEN(如有)
if(令牌头){
extend(config.headers、tokenHeaders);
}
//添加标志_________________________________________________
//向每个请求添加withCredentials
//需要,因为我们在请求头中发送cookie
config.withCredentials=true;
返回配置;
};

这个答案已经发布很久了。但是你有没有可能举一个例子说明你如何提出进一步的后续请求?我很难做到这一点。我可以登录并存储所有用户会话详细信息以及令牌(发送回cookie和X-CSRF-token).但每次我向drupal发出进一步请求时,它都会返回“用户未登录”错误。