我的 jquery AJAX POST 请求无需发送真实性令牌(Rails)即可工作
Posted
技术标签:
【中文标题】我的 jquery AJAX POST 请求无需发送真实性令牌(Rails)即可工作【英文标题】:My jquery AJAX POST requests works without sending an Authenticity Token (Rails) 【发布时间】:2011-03-04 19:42:51 【问题描述】:rails 中是否有任何规定允许来自站点的所有 AJAX POST 请求在没有authentity_token 的情况下通过?
我有一个调用控制器方法的 Jquery POST ajax 调用,但我没有在其中放入任何真实性代码,但调用成功。
我的 ApplicationController 确实有 'request_forgery_protection' 我已经改变了
config.action_controller.consider_all_requests_local
在我的环境/development.rb 中设置为 false
我还搜索了我的代码,以确保我没有重载 ajaxSend 来发送真实性令牌。
是否有某种机制可以禁用检查?现在我不确定我的 CSRF 保护是否有效。
我使用的是 Rails 2.3.5。
更新清晰:
function voteup(url, groupid)
$.ajax(
type: "POST",
url: "/groups/" + groupid + "/submissions/voteup",
data: "url=" + url,
dataType: 'text',
success: function(data)
var counter = "vote_" + url;
$('#vote_' + url.cleanify()).text(" " + data + " ");
);
;
我有一个链接,然后有一个调用上述函数的'href:
<a href='javascript:voteup(param1,param2)'>...</a>
【问题讨论】:
我记得回答过一个类似的问题.. 在这里找到它:***.com/questions/2725118/… 我想应该是因为它是本地请求。从在不同端口或不同域上运行的应用程序说,它不应该工作。例如:如果您的应用程序在 localhost:3000 上运行,您应该无法从 localhost:3001 执行 ajax POST。 嗨 Shripad,我看到了你的帖子,但这是怎么回事?是否涉及某种 Rails 魔法?在网上看,我仍然看到有人写关于发送 form_authenticity_token 的说明,所以如果它已修复,为什么还需要这样做? 这与 Rails 的魔法无关。如果在域本身内调用 Ajax,则无需真实性令牌即可工作。您需要一个真实性令牌,不是为了让 ajax 在您的域上工作,而是为了防止来自其他域的攻击。这是在您的应用程序控制器中使用protect_from_forgery
的主要原因。来自另一个域的攻击的最佳示例是“Myspace sammy worm”。查一下。然后你就会明白为什么你需要一个身份验证令牌。
【参考方案1】:
这里可能的情况是,您正在使用 jQuery 序列化一个普通的 Rails 表单......它包括序列化的身份验证令牌隐藏字段(Rails 将它们添加到所有表单)。
查看您正在提交的表单的生成源...您很可能会看到
<input name="authenticity_token" type="hidden" value="somethinghere...." />
您可以做的另一件事是检查日志以查看authentity_token 字段是否在请求参数中。
【讨论】:
我已经用一些代码示例更新了这个问题。我的日志没有显示正在发送的authenticity_token 参数。【参考方案2】:在你的布局视图中添加这个:app/views/layouts/(something).html.erb
<% if protect_against_forgery? %>
<script type="text/javascript" charset="utf-8">
//<![CDATA[
window._auth_token_name = "#request_forgery_protection_token";
window._auth_token = "#form_authenticity_token";
//]]>
</script>
<% end %>
在你的 application.js 中:
$.ajaxSetup(
'beforeSend': function(xhr) xhr.setRequestHeader("Accept", "text/javascript")
);
$(document).ready(function()
// All non-GET requests will add the authenticity token
// If not already present in the data packet
$("body").bind('ajaxSend', function(elm, xhr, s)
if (s.type == "GET") return;
if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
if (s.data)
s.data = s.data + "&";
else
s.data = "";
// if there was no data, $ didn't set the content-type
xhr.setRequestHeader("Content-Type", s.contentType);
s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token);
);
在你的 application_controller.rb 中添加这个以确保 IE/SAFARI 接收到正确的接受标头:
def correct_safari_and_ie_accept_headers
ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml']
request.accepts.sort! |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 if request.xhr?
end
这确保接受标头默认为text/javascript
、application/json
或text/xml
,而不是默认的text/html
。
现在您可以执行常规的 AJAX 调用了。它将传递身份验证令牌。还要确保仅在 CDATA 脚本标记之后包含 application.js,因为它需要两个全局变量 window._auth_token_name
和 window._auth_token
。
希望这会有所帮助!干杯:)
【讨论】:
感谢代码,但我的问题是,在这个时间点,即使没有身份验证令牌,我的帖子也能正常工作。以上是关于我的 jquery AJAX POST 请求无需发送真实性令牌(Rails)即可工作的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Laravel 中使用 jQuery ajax 请求自动添加 X-CSRF-TOKEN
如何使用 Symfony 和 Jquery 发出 POST Ajax 请求
使用 Laravel 将 jQuery Ajax POST 请求作为 GET 发送