2011-02-26 12 views
60

Tengo un problema muy extraño con Rails y ajax con jQuery (aunque no creo que sea específico de jQuery).Rieles que no vuelven a cargar la sesión en la publicación de ajax

La aplicación My Rails utiliza el almacén de sesiones de cookies, y tengo un inicio de sesión muy simple que establece la identificación del usuario en la sesión. Si user_id no está configurado en la sesión, redirige a una página de inicio de sesión. Esto funciona sin problemas. Las solicitudes JQuery GET también funcionan bien. El problema es cuando hago una POST jQuery - el navegador envía la cookie de sesión bien (confirmé esto con Firebug y volcando request.cookies en el registro) pero la sesión está en blanco, es decir, la sesión es {}.

que estoy haciendo esto en mis application.js:

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

y aquí está mi puesto de ejemplo:

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

que debe llegar a este método controlador (_method: eliminar):

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

Al mirar el registro y el uso de Firebug puedo confirmar que se envía el valor correcto de la cookie en la solicitud que ader cuando se produce la publicación ajax, pero parece que en algún momento Rails pierde este valor y, por lo tanto, pierde la sesión, por lo que redirige a la página de inicio de sesión y nunca llega al método.

He intentado todo lo que puedo pensar para depurar esto, pero estoy llegando a la idea de que esto podría ser un error en Rails. Estoy usando Rails 3.0.4 y jQuery 1.5 si eso ayuda. Me resulta muy extraño que funcionen las solicitudes de envío y publicación regulares (es decir, no ajax), y las solicitudes de ajax funcionan sin problemas, solo son las publicaciones ajax las que no lo hacen.

¡Cualquier ayuda para tratar de arreglar esto sería muy apreciada!

Muchas gracias,
de Dave

Respuesta

112

voy a responder a mi propia pregunta como me las he arreglado para averiguar lo que estaba pasando. Lo publicaré aquí en caso de que sea útil para cualquier otra persona.

Después de investigar más, me di cuenta de que el código que era supuesto para establecer el encabezado de solicitud con el token CSRF, no lo era. Este fue el código original:

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

Lo que estaba ocurriendo era que este código no se ha fijado la cabecera, rieles estaba recibiendo una petición Ajax, el token no produjo y fue restableciendo la sesión. Esto solía generar un error de ActionController :: InvalidAuthenticityToken (supongo que habría detectado esto antes si se hubiera producido un error ... bueno), pero desde Rails 3.0.4 ahora simplemente reinicia silenciosamente la sesión.

Así que para enviar el token en la cabecera, que tiene que hacer esto (muchas gracias a this marvellous blog post):

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

Y ahora todo funciona como debería. Lo cual es bueno.

0

Para eso está el official jquery-ujs rails adapter en la serie 3.0. Sin embargo, debe recordar mantenerla actualizada al actualizar versiones de rieles.

Para mí, actualizando de 3.0.3 a 3.0.8.rc4 significa también obtener manualmente el archivo src/rails.js del repositorio vinculado.

Desde Rails 3.1, finalmente hecho el cambio a jQuery, las cosas deben de actualización automática en el futuro a través de la gema jquery-rails al actualizar carriles (y el uso de tubería activo incorporado en 3.1)

5

encontré otra caso:

¿ha configurado el 'csrf_meta_tag' en el archivo de diseño de la aplicación?

en mi caso, no configuré esa etiqueta, y encontré el mismo problema con la suya.

Y después de configurar el csrf_meta_tag en la aplicación/views/layouts/application.html.erb, ¡todo funciona bien!

¡Por fin, gracias por ayudarme a encontrar la causa raíz! muchas gracias ~

+0

Esta etiqueta ha sido reemplazada con 'csrf_meta_tags' – ChrisW

Cuestiones relacionadas