rails - 针对json/xml请求的InvalidAuthenticityToken
出于某种原因,当使用json或xml向我的应用程序发送发布请求时,我得到一个InvalidAuthenticityToken。我的理解是,轨道应该只需要一个真实性标记为html或js请求,因此我不应该遇到这个错误。我迄今为止发现的唯一解决方案是禁用protect_from_forgery,以便通过API访问任何操作,但由于显而易见的原因,这并不理想。思考?rails - 针对json/xml请求的InvalidAuthenticityToken
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
,这就是我得到的日志每当我传递给动作的请求:
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
我也有类似的情况,问题是,我是不是通过正确的内容发送键入标题 - 我要求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
或者你可以在JSON保存到本地文件,并调用curl
这样的:
curl -H "Content-Type: application/json" -v -d @person.json -X POST http://localhost:3000/people.json -i
当我将内容类型标题更改为application/json
所有我的麻烦消失了,我不再需要禁用伪造保护。
启用protect_from_forgery
后,Rails需要一个真实性标记用于任何非GET请求。 Rails会自动将真实性标记包含在使用表单助手创建的表单中,或者使用AJAX助手创建的链接 - 因此在正常情况下,您不必考虑它。
如果您不使用内置的Rails表单或AJAX帮助程序(也许您在使用JS或使用JS MVC框架),您必须自己在客户端设置令牌并发送它在提交POST请求时与您的数据一起。你把这样一行在布局的<head>
:
<%= javascript_tag "window._token = '#{form_authenticity_token}'" %>
那么你的AJAX功能将发布令牌与其他数据(例如使用jQuery):
$.post(url, {
id: theId,
authenticity_token: window._token
});
Optimate应该接受这个答案。顺便说一下,如果你使用'$ .ajax',你需要将真实性标记置于数据字段中,如下所示:'$ .ajax({data:{authenticity_token:window._token}})' – 2016-11-22 18:29:10
加起来andymism的答案,你可以使用这个应用在每一个POST请求令牌的默认包含:
$(document).ajaxSend(function(event, request, settings) {
if (settings.type == 'POST' || settings.type == 'post') {
settings.data = (settings.data ? settings.data + "&" : "")
+ "authenticity_token=" + encodeURIComponent(window._token);
}
});
api_key的要点是为了避免出现auth_token – NullVoxPopuli 2012-02-29 23:14:18
另一种方法是避免verify_authenticity_token使用skip_before_filter您Rails App:
skip_before_action :verify_authenticity_token, only: [:action1, :action2]
这会让curl去完成它的工作。
要添加到阿隆索的回答,如果你的控制器既响应JSON和HTML,您可以使用:
skip_before_filter :verify_authenticity_token, if: :json_request?
这不是安全风险吗? – 2016-11-22 17:53:12
这是一样的@user1756254's answer但在Rails的5,你需要使用多一点不同的语法:
protect_from_forgery unless: -> { request.format.json? }
来源:http://api.rubyonrails.org/v5.0/classes/ActionController/RequestForgeryProtection.html
这不是安全风险吗? – 2016-11-22 17:53:31
@WylliamJudd否,仅为JSON禁用它并不构成安全风险,因为伪造保护目标是保护从其他网站提交的HTML表单 – edwardmp 2016-11-22 19:11:28
当官方文档显示:_'if您正在构建一个API,你应该改变ApplicationController中的伪造保护方法(默认情况下::exception)'_,那么它足够安全 – 2017-08-30 23:36:12
这并不能真正为Web应用程序的工作,虽然。浏览器无法运行卷曲。 =( – NullVoxPopuli 2012-02-29 23:14:55
问题是我用curl调试了这个问题,发现发送正确的Content-Type头是很重要的。 – mlambie 2012-03-07 03:35:08