recover from bad CSRF tokens without requiring a hard refresh of the browser

This commit is contained in:
Sam 2013-08-27 15:56:12 +10:00
parent bec463564f
commit c4a0152dc6
5 changed files with 16 additions and 9 deletions

View File

@ -132,13 +132,13 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
});
// Add a CSRF token to all AJAX requests
var csrfToken = $('meta[name=csrf-token]').attr('content');
Discourse.csrfToken = $('meta[name=csrf-token]').attr('content');
console.log(Discourse.csrfToken);
$.ajaxPrefilter(function(options, originalOptions, xhr) {
if (!options.crossDomain) {
// This may be delay set
csrfToken = csrfToken || $('meta[name=csrf-token]').attr('content');
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
xhr.setRequestHeader('X-CSRF-Token', Discourse.csrfToken);
}
});

View File

@ -56,6 +56,12 @@ Discourse.Ajax = Em.Mixin.create({
var oldError = args.error;
args.error = function(xhr) {
// note: for bad CSRF we don't loop an extra request right away.
// this allows us to eliminate the possibility of having a loop.
if (xhr.status === 403 && xhr.responseText == "['BAD CSRF']") {
Discourse.csrfToken = null;
}
// If it's a parseerror, don't reject
if (xhr.status === 200) return args.success(xhr);
@ -73,12 +79,11 @@ Discourse.Ajax = Em.Mixin.create({
// For cached pages we strip out CSRF tokens, need to round trip to server prior to sending the
// request (bypass for GET, not needed)
var csrfToken = $('meta[name=csrf-token]').attr('content');
if(args.type && args.type !== 'GET' && !csrfToken){
if(args.type && args.type !== 'GET' && !Discourse.csrfToken){
return Ember.Deferred.promise(function(promise){
$.ajax(Discourse.getURL('/session/csrf'))
.success(function(result){
$('head').append('<meta name="csrf-token" content="' + result.csrf + '">');
Discourse.csrfToken = result.csrf;
performAjax(promise);
});
});

View File

@ -22,7 +22,7 @@ class ApplicationController < ActionController::Base
unless is_api?
super
clear_current_user
raise Discourse::CSRF
render text: "['BAD CSRF']", status: 403
end
end

View File

@ -67,7 +67,7 @@ class SessionController < ApplicationController
end
def destroy
session[:current_user_id] = nil
reset_session
cookies[:_t] = nil
render nothing: true
end

View File

@ -83,6 +83,8 @@ class Users::OmniauthCallbacksController < ApplicationController
# log on any account that is active with forum access
if Guardian.new(user).can_access_forum? && user.active
log_on_user(user)
# don't carry around old auth info, perhaps move elsewhere
session[:authentication] = nil
@data.authenticated = true
else
if SiteSetting.invite_only?