在AJAX请求之后,Devise + Rails 3.0.4结束会话

fut*_*ked 7 ajax session devise ruby-on-rails-3

我已经通过生成一个AJAX请求触发的动作Ajax.InPlaceEditor或者InPlaceCollectionEditor是这样的:

new Ajax.InPlaceCollectionEditor('agent_email', 'inspections/<%= @inspection.id %>/update_field', 
{
collection: [<% @agents.each do |agent| %>
        '<%= agent.email %>',           
        <% end %>],
    okText: 'Update',
    cancelText: 'Never mind',
    savingText: 'Updating...'

});
Run Code Online (Sandbox Code Playgroud)

在另一端,该操作包含:

def update_field
  --some code here--
  if success
    puts "stored change"
    render :text => result
  else
    puts "did note change store"
    render :text => inspection.errors.to_json, :status => 500
  end
end
Run Code Online (Sandbox Code Playgroud)

一旦到达任何渲染方法,会话就会到期,并且下次用户发送请求时,Devise会将它们发送到登录页面.

即使我从update(before_filter :authenticate_user!, :except => :update_field)中免除update_field ,会话仍然会被重置.

我在Devise会话上看到了一个非常类似的问题的答案,它立即在.js调用[AJAX]上到期,但它并没有解决我的特定问题.

有任何想法吗?

fut*_*ked 11

我通过从http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails(prototype-snippet.js)获取代码来实现这一目的:

/*
 * Registers a callback which copies the csrf token into the
 * X-CSRF-Token header with each ajax request.  Necessary to 
 * work with rails applications which have fixed
 * CVE-2011-0447
*/

Ajax.Responders.register({
onCreate: function(request) {
  var csrf_meta_tag = $$('meta[name=csrf-token]')[0];

  if (csrf_meta_tag) {
    var header = 'X-CSRF-Token',
        token = csrf_meta_tag.readAttribute('content');

    if (!request.options.requestHeaders) {
      request.options.requestHeaders = {};
    }
    request.options.requestHeaders[header] = token;
  }
}
});
Run Code Online (Sandbox Code Playgroud)

...在我的application.html.erb的Javascript块中:

<script type="text/javascript">
  (... the code from above)
</script>
Run Code Online (Sandbox Code Playgroud)

另外别忘了添加:

<%= csrf_meta_tag %>
Run Code Online (Sandbox Code Playgroud)

在顶部的同一个文件中(如果还没有).

文档" Ruby on Rails中的CSRF保护绕过 "解释了为什么这有效.