- 在 Rails 页面上使用
$.Ajax
发送一个最简单的的post
请求,结果遇到了InvalidAuthenticityToken
错误
- 如果使用
form_for ... remote:true
的话完全正常
- 我明白
Rails
的helper
里面自动加了X-CSRF-Token:
我的问题是:难道在不使用remote: true
的时候,都需要自己在Ajax
请求里面加上X-CSRF-Token:
么?
版本信息
- OS : MacOS 10.9.2
- Rails : 4.0.2
- Ruby : 2.0.0-p353
代码
- 前提:
rails g scaffold posts title content:text
views/posts/index.html.erb
<form action="/posts" method="POST">
<input type="text" id="title">
<input type="submit" id="ajax_submit">
</form>
assets/javascript/posts.js.coffee
$ ->
$('#ajax_submit').click (event) ->
event.preventDefault() # 最开始的时候忘记加这句了,导致默认的提交动作也被执行了
$.ajax(
type: "POST"
url: "/posts"
data: {
title: $('#post_title')
}
success: ->
alert "success"
)
分析过程(jquery_ujs.js)
- 首先,有一个
rails.CSRFProtection
函数。它的作用就是向ajax
请求的headers
中加入csrf token
信息,代码如下
CSRFProtection: function(xhr) {
var token = $('meta[name="csrf-token"]').attr('content');
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
},
if (rails.fire($document, 'rails:attachBindings')) { # 这句是触发`rails:attachBindings`事件
$.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
-
rails:attachBindings
事件:查看change log
可以看到,是为了增加$.rails
的自定义设置。所以没有自定义的前提下,触发事件这句代码不会失败
## 2.0.3 (16 August 2012)
- Updated to latest jquery-ujs
- created `rails:attachBindings` to allow for customization of $.rails object settings
- created `ajax:send` event to provide access to jqXHR object from ajax requests
- added support for `data-with-credentials`
- 也就意味着,
$.ajaxPrefilter(...
这一句肯定会被执行
- 也就是说:引入了
jquery_ujs.js
的前提下,所有的ajax
请求都会自动被加入csrf token
结论
- 在
rails
项目中,所有非跨站的ajax
请求都会被自动加入csrf token
信息,不需要自己去做