开发者

Rails not reloading session on ajax post

I'm experiencing a very strange problem with Rails and ajax using jQue开发者_运维问答ry (although I don't think it's specific to jQuery).

My Rails application uses the cookie session store, and I have a very simple login that sets the user id in the session. If the user_id isn't set in the session, it redirects to a login page. This works with no problems. JQuery GET requests work fine too. The problem is when I do a jQuery POST - the browser sends the session cookie ok (I confirmed this with Firebug and dumping request.cookies to the log) but the session is blank, i.e. session is {}.

I'm doing this in my application.js:

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

and here is my sample post:

$.post('/test/1', { _method: 'delete' }, null, 'json');

which should get to this controller method (_method: delete):

def destroy
  respond_to do |format|
    format.json { render :json => { :destroyed => 'ok' }.to_json }
  end
end

Looking at the log and using Firebug I can confirm that the correct cookie value is sent in the request header when the ajax post occurs, but it seems that at some point Rails loses this value and therefore loses the session, so it redirects to the login page and never gets to the method.

I've tried everything I can think of to debug this but I'm coming around to the idea that this might be a bug in Rails. I'm using Rails 3.0.4 and jQuery 1.5 if that helps. I find it very strange that regular (i.e. non-ajax) get and post requests work, and ajax get requests work with no problems, it's just the ajax posts that don't.

Any help in trying to fix this would be greatly appreciated!

Many thanks,

Dave


I'm going to answer my own question as I've managed to work out what was going on. I'll post it here in case it's useful to anyone else!

After investigating further, I worked out that the code that was supposed to be setting the request header with the CSRF token, wasn't. This was the original code:

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

What was happening was that this code wasn't setting the header, Rails was receiving an Ajax request, the token didn't match and it was resetting the session. This used to raise an ActionController::InvalidAuthenticityToken error (I suppose I would have caught this earlier if an error was raised... oh well), but since Rails 3.0.4 it now just quietly resets the session.

So to send the token in the header, you have to do this (many thanks to this marvellous blog post):

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
  }
}); 

And now it all works as it should. Which is nice.


I found another case:

have you set the 'csrf_meta_tag' in your application layout file?

in my case, I didn't set that tag, and met the same problem with yours.

And after setting the csrf_meta_tag in app/views/layouts/application.html.erb, everything works fine!

At last, thank you for helping me found the root cause ! thanks a lot ~


That's what the official jquery-ujs rails adapter is for in the 3.0 series. You have to remember to keep it updated when upgrading rails versions though.

For me, upgrading from 3.0.3 to 3.0.8.rc4 meant also manually fetching the src/rails.js file from the linked repo.

Since Rails 3.1 finally made the switch to jQuery, things should auto-update in the future via the jquery-rails gem when updating rails (and using 3.1's built-in asset pipeline)


If you still have problem after sending csrf_meta_tag correctly to the server. Be sure your session store configuration is correct.

If the :secure is set to true in your session_store.rb, the cookie (session) won't be transmitted to your http server. docs: https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜