-->

Rails的CSRF保护+ Angular.js:protect_from_forgery让我退出上

2019-07-19 10:24发布

如果protect_from_forgery选项在application_controller提到的,然后我就可以登录并执行任何GET请求,但在第一个POST请求Rails的重置会话,它记录了我。

我把protect_from_forgery选项暂时关闭,但想与Angular.js使用它。 是否有某种方式来做到这一点?

Answer 1:

我觉得从DOM读取CSRF价值是不是一个很好的解决方案,它只是一个解决方法。

下面是一个文件的形式angularJS官方网站http://docs.angularjs.org/api/ng.$http :

由于只在您的域中可以读取cookie中运行的JavaScript,您的服务器可以放心的是,XHR从JavaScript来在域上运行。

要充分利用这一点(CSRF保护),你的服务器需要设置令牌名为XSRF-TOKEN的第一个HTTP GET请求一个JavaScript可读会话cookie。 在随后的非GET请求的服务器可以验证cookie的比赛X-XSRF-TOKEN HTTP标头

下面是根据这些说明我的解决方案:

首先,设置Cookie:

# app/controllers/application_controller.rb

# Turn on request forgery protection
protect_from_forgery

after_action :set_csrf_cookie

def set_csrf_cookie
  cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end

那么,我们应该核实每一个非GET请求令牌。
由于滑轨已经用相似的方法建立,我们可以只是简单的覆盖它追加我们的逻辑:

# app/controllers/application_controller.rb

protected

  # In Rails 4.2 and above
  def verified_request?
    super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
  end

  # In Rails 4.1 and below
  def verified_request?
    super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
  end


Answer 2:

如果您使用的是默认的Rails CSRF保护( <%= csrf_meta_tags %> ),你可以配置你喜欢这个角模块:

myAngularApp.config ["$httpProvider", ($httpProvider) ->
  $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
]

或者,如果你不使用CoffeeScript的(什么!?):

myAngularApp.config([
  "$httpProvider", function($httpProvider) {
    $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
  }
]);

如果你愿意,你可以只发送与类似下面的非GET请求头:

myAngularApp.config ["$httpProvider", ($httpProvider) ->
  csrfToken = $('meta[name=csrf-token]').attr('content')
  $httpProvider.defaults.headers.post['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.put['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.patch['X-CSRF-Token'] = csrfToken
  $httpProvider.defaults.headers.delete['X-CSRF-Token'] = csrfToken
]

此外,一定要检查出HungYuHei的答案 ,它涵盖了服务器,而不是在客户端上的所有基地。



Answer 3:

该angular_rails_csrf宝石会自动为所描述的模式支持HungYuHei的回答您的所有控制器:

# Gemfile
gem 'angular_rails_csrf'


Answer 4:

该合并所有以前的答案的答案,它依赖于你正在使用Devise认证的宝石。

首先,添加宝石:

gem 'angular_rails_csrf'

接下来,添加rescue_from块到application_controller.rb:

protect_from_forgery with: :exception

rescue_from ActionController::InvalidAuthenticityToken do |exception|
  cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
  render text: 'Invalid authenticity token', status: :unprocessable_entity
end

而最后,拦截模块添加到您的角度应用。

# coffee script
app.factory 'csrfInterceptor', ['$q', '$injector', ($q, $injector) ->
  responseError: (rejection) ->
    if rejection.status == 422 && rejection.data == 'Invalid authenticity token'
        deferred = $q.defer()

        successCallback = (resp) ->
          deferred.resolve(resp)
        errorCallback = (resp) ->
          deferred.reject(resp)

        $http = $http || $injector.get('$http')
        $http(rejection.config).then(successCallback, errorCallback)
        return deferred.promise

    $q.reject(rejection)
]

app.config ($httpProvider) ->
  $httpProvider.interceptors.unshift('csrfInterceptor')


Answer 5:

我看到其他的答案,并认为他们是伟大的和深思熟虑。 我得到了我的Rails应用程序的工作,虽然什么我认为是一个简单的解决方案,所以我想我会分享。 我的Rails应用程序来使用这个默认的它,

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
end

我读了意见,并就好像这是我想要使用的角度,避免CSRF错误的东西。 我改成了这一点,

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :null_session
end

现在,它的作品! 我看不出有任何理由,这不应该工作,但我很乐意听到来自其他海报的一些见解。



Answer 6:

我用从HungYuHei的回答内容在我的应用程序。 我发现,我不过是处理一些额外的问题,我使用的设计认证的一些原因,有些是因为我有我的申请得到了默认的:

protect_from_forgery with: :exception

我注意到相关堆栈溢出的问题,有答案 ,我写了一个更详细的博客文章 ,总结多方面考虑。 该溶液的是与此有关的,在应用控制器中的部分:

  protect_from_forgery with: :exception

  after_filter :set_csrf_cookie_for_ng

  def set_csrf_cookie_for_ng
    cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
  end

  rescue_from ActionController::InvalidAuthenticityToken do |exception|
    cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
    render :error => 'Invalid authenticity token', {:status => :unprocessable_entity} 
  end

protected
  def verified_request?
    super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
  end


Answer 7:

我发现了一个非常快速的黑客攻击了这一点。 所有我必须做的是以下几点:

一个。 在我看来,我初始化$scope包含令牌变量,假设的形式之前,或者在控制器初始化甚至更好:

<div ng-controller="MyCtrl" ng-init="authenticity_token = '<%= form_authenticity_token %>'">

湾 在我的AngularJS控制器,节省了我的新的项目之前,我的代币添加到哈希:

$scope.addEntry = ->
    $scope.newEntry.authenticity_token = $scope.authenticity_token 
    entry = Entry.save($scope.newEntry)
    $scope.entries.push(entry)
    $scope.newEntry = {}

做没有更多的需求。



Answer 8:

 angular
  .module('corsInterceptor', ['ngCookies'])
  .factory(
    'corsInterceptor',
    function ($cookies) {
      return {
        request: function(config) {
          config.headers["X-XSRF-TOKEN"] = $cookies.get('XSRF-TOKEN');
          return config;
        }
      };
    }
  );

它的工作对angularjs身边!



文章来源: Rails CSRF Protection + Angular.js: protect_from_forgery makes me to log out on POST