rails - json/xml请求的InvalidAuthenticityToken

Opt*_*ate 21 json ruby-on-rails restful-authentication

出于某种原因,当使用json或xml向我的应用程序发出请求时,我得到一个InvalidAuthenticityToken.我的理解是rails应该只为html或js请求提供真实性令牌,因此我不应该遇到这个错误.到目前为止,我发现的唯一解决方案是禁用protect_from_forgery来执行我想通过API访问的任何操作,但由于显而易见的原因,这并不理想.思考?

    def create
    respond_to do |format|
        format.html
        format.json{
            render :json => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar])
        }
        format.xml{
            render :xml => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar])
        }
    end
end
Run Code Online (Sandbox Code Playgroud)

每当我将请求传递给操作时,这就是我在日志中获得的内容:

 Processing FooController#create to json (for 127.0.0.1 at 2009-08-07 11:52:33) [POST]
 Parameters: {"foo"=>"1", "api_key"=>"44a895ca30e95a3206f961fcd56011d364dff78e", "bar"=>"202"}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
  thin (1.2.2) lib/thin/connection.rb:76:in `pre_process'
  thin (1.2.2) lib/thin/connection.rb:74:in `catch'
  thin (1.2.2) lib/thin/connection.rb:74:in `pre_process'
  thin (1.2.2) lib/thin/connection.rb:57:in `process'
  thin (1.2.2) lib/thin/connection.rb:42:in `receive_data'
  eventmachine (0.12.8) lib/eventmachine.rb:242:in `run_machine'
  eventmachine (0.12.8) lib/eventmachine.rb:242:in `run'
  thin (1.2.2) lib/thin/backends/base.rb:57:in `start'
  thin (1.2.2) lib/thin/server.rb:156:in `start'
  thin (1.2.2) lib/thin/controllers/controller.rb:80:in `start'
  thin (1.2.2) lib/thin/runner.rb:174:in `send'
  thin (1.2.2) lib/thin/runner.rb:174:in `run_command'
  thin (1.2.2) lib/thin/runner.rb:140:in `run!'
  thin (1.2.2) bin/thin:6
  /opt/local/bin/thin:19:in `load'
  /opt/local/bin/thin:19
Run Code Online (Sandbox Code Playgroud)

and*_*wle 26

随着protect_from_forgery启用时,Rails需要任何非GET请求的真实性令牌.Rails会自动在使用表单助手创建的表单中包含真实性令牌或使用AJAX助手创建的链接 - 因此在正常情况下,您不必考虑它.

如果您没有使用内置的Rails表单或AJAX助手(也许您正在使用不引人注目的JS或使用JS MVC框架),您必须自己在客户端设置令牌并将其与您一起发送提交POST请求时的数据.你在<head>你的布局中添加了这样的一行:

<%= javascript_tag "window._token = '#{form_authenticity_token}'" %>
Run Code Online (Sandbox Code Playgroud)

然后你的AJAX函数会使用你的其他数据发布令牌(例如jQuery):

$.post(url, {
    id: theId,
    authenticity_token: window._token
});
Run Code Online (Sandbox Code Playgroud)

  • Optimate应该接受这个答案.顺便说一句,如果你使用`$ .ajax`,你需要将真实性标记放在数据字段中,如下所示:`$ .ajax({data:{authenticity_token:window._token}})` (2认同)

mla*_*bie 12

我有类似的情况,问题是我没有发送正确的内容类型标题 - 我正在请求text/json,我本应该请求application/json.

我使用curl以下方法测试我的应用程序(根据需要进行修改):

curl -H "Content-Type: application/json" -d '{"person": {"last_name": "Lambie","first_name": "Matthew"}}' -X POST http://localhost:3000/people.json -i
Run Code Online (Sandbox Code Playgroud)

或者您可以将JSON保存到本地文件并curl像这样调用:

curl -H "Content-Type: application/json" -v -d @person.json -X POST http://localhost:3000/people.json -i
Run Code Online (Sandbox Code Playgroud)

当我将内容类型标题更改为右侧时,application/json我的所有麻烦都消失了,我不再需要禁用伪造保护.

  • 关键是我用curl调试了这个问题,发现发送正确的Content-Type标头很重要. (4认同)

edw*_*dmp 12

这与@ user1756254的答案相同,但在Rails 5中,您需要使用更多不同的语法:

protect_from_forgery unless: -> { request.format.json? }
Run Code Online (Sandbox Code Playgroud)

资料来源:http://api.rubyonrails.org/v5.0/classes/ActionController/RequestForgeryProtection.html

  • 这不是安全隐患吗? (4认同)
  • 当官方文档说:_如果你正在构建一个API,你应该在ApplicationController中更改伪造保护方法(默认情况下::exception)'_,那么它足够安全 (2认同)