No modifications to work with CSRF protection were applied to the in_place_editing plugin, as a result it doesn't work at all with CSRF protection turned on.
Also, scriptaculous/prototype have moved away from the evalScripts option for Ajax.Request, the option is now htmlResponse (htmlResponse should be the opposite of the old evalScripts). As a result at the moment for some requests the RJS does not get evaluated and instead is inserted into the page as escaped text.
Attached is a patch that fixes both these issues in the plugin, including additional tests.
Also changed: added the :text_between_controls option available in modern scriptaculous, for rendering things like <input type="submit" value="Save"/> or <a href="whatever">cancel</a>.
lib/in_place_macros_helper.rb
old | new | |
---|---|---|
40 | 40 | function << "'#{url_for(options[:url])}'" |
41 | 41 | |
42 | 42 | js_options = {} |
43 | ||
44 | if protect_against_forgery? | |
45 | options[:with] ||= "Form.serialize(form)" | |
46 | options[:with] += " + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')" | |
47 | end | |
48 | ||
43 | 49 | js_options['cancelText'] = %('#{options[:cancel_text]}') if options[:cancel_text] |
44 | 50 | js_options['okText'] = %('#{options[:save_text]}') if options[:save_text] |
45 | 51 | js_options['loadingText'] = %('#{options[:loading_text]}') if options[:loading_text] |
… | … | |
50 | 56 | js_options['externalControl'] = "'#{options[:external_control]}'" if options[:external_control] |
51 | 57 | js_options['loadTextURL'] = "'#{url_for(options[:load_text_url])}'" if options[:load_text_url] |
52 | 58 | js_options['ajaxOptions'] = options[:options] if options[:options] |
53 | js_options[' | |
59 | js_options['htmlResponse'] = !options[:script] if options[:script] | |
54 | 60 | js_options['callback'] = "function(form) { return #{options[:with]} }" if options[:with] |
55 | 61 | js_options['clickToEditText'] = %('#{options[:click_to_edit_text]}') if options[:click_to_edit_text] |
62 | js_options['textBetweenControls'] = %('#{options[:text_between_controls]}') if options[:text_between_controls] | |
56 | 63 | function << (', ' + options_for_javascript(js_options)) unless js_options.empty? |
57 | 64 | |
58 | 65 | function << ')' |
说是rails2.0以后,内置了一个防止CSRF (Cross-Site Request Forgery)攻击的功能,protect_from_forgery 方法。
解决办法是在in_place_macros_helper.rb 文件中加了一段代码:
if protect_against_forgery?
options[:with] ||= "Form.serialize(form)"
options[:with] += " + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')"
end
删除
js_options['
添加
js_options[' htmlResponse'] = !options[:script] if options[:script]
js_options['textBetweenControls'] = %('#{options[:text_between_controls]}') if options[:text_between_controls]
引用:http://dev.rubyonrails.org/ticket/10055
http://dev.rubyonrails.org/attachment/ticket/10055/in_place_editing_should_work_with_csrf_and_rjs.patch
另一解决方法:(不安全)
由于我的rails是从rails1。0升级到2。1。2的,所以在test环境中也会使用Request forgery protection(防止csrf)攻击功能,所以在environment.rb文件中设置如下,可取消保护
config.action_controller.allow_forgery_protection = false