2010-06-17 12 views
5

¿Hay alguna disposición en los rieles que permita que todas las solicitudes AJAX POST del sitio pasen sin autenticidad_token?Mi jquery POST AJAX solicita trabajos sin enviar un token de autenticidad (rieles)

Tengo una llamada Jquery POST ajax que llama a un método de controlador, pero no puse ningún código de autenticidad en ella y, sin embargo, la llamada tiene éxito.

Mi ApplicationController tiene 'request_forgery_protection' y he cambiado

config.action_controller.consider_all_requests_local 

en false en mis entornos/development.rb

también he buscado mi código para asegurarse de que no estaba sobrecargando ajaxEnviar para enviar tokens de autenticidad.

¿Hay algún mecanismo en juego que deshabilite el cheque? Ahora no estoy seguro de si mi protección CSRF está funcionando o no.

Estoy usando Rails 2.3.5.

actualización para mayor claridad:

function voteup(url, groupid){ 
     $.ajax({ 
     type: "POST", 
     url: "/groups/" + groupid + "/submissions/voteup", 
     data: "url=" + url, 
     dataType: 'text', 
     success: function(data){ 
      var counter = "vote_" + url; 
      $('#vote_' + url.cleanify()).text(" " + data + " "); 
     } 
     }); 
    }; 

tengo un vínculo que luego tiene un 'href que llama a la función anterior:

<a href='javascript:voteup(param1,param2)'>...</a> 
+0

recordé responder a una pregunta similar .. encontré aquí: http://stackoverflow.com/questions/2725118/rails-request-forgery-protection-settings/2725991 # 2725991 Supongo que debería ser porque es una solicitud local. No debería funcionar, por ejemplo, desde una aplicación que se ejecuta en un puerto diferente o en un dominio diferente. Ejemplo: si tienes tu aplicación ejecutándose en localhost: 3000 no deberías poder hacer una POST ajax desde localhost: 3001. –

+0

Hola Shripad, Vi su publicación, pero ¿cómo está sucediendo esto? ¿Hay algún tipo de magia de Rails involucrada? Buscando en línea, todavía veo personas escribiendo sobre las instrucciones para enviar form_authenticity_token, por lo que si está solucionado, ¿por qué hay una necesidad de hacer eso? –

+0

Esto no tiene nada que ver con la magia de Rails en absoluto. Ajax funciona sin un token de autenticidad si se invoca dentro del dominio mismo. Necesita un token de autenticidad no para permitir que ajax trabaje en su dominio sino para evitar ataques de otros dominios. Esa es la razón principal para tener 'protect_from_forgery' en su controlador de aplicación. El mejor ejemplo de un ataque de otro dominio es el "gusano de Myspace sammy". Búscalo. Entonces comprenderá por qué necesita un token de autenticación. –

Respuesta

6

Un escenario más probable es que aquí está utilizando jQuery para serializar un formulario de Rails normal ... y está incluido en que el campo oculto de token de autenticación en serie (Rails los agrega a todos los formularios).

Mire a su fuente generado para la forma que vas a enviar ... lo más probable es que usted verá

<input name="authenticity_token" type="hidden" value="somethinghere...." /> 

La otra cosa que puede hacer es comprobar el registro para ver si el campo está en authenticity_token los params de solicitud.

+1

He actualizado la pregunta con algunos ejemplos de código. Mis registros no muestran un param autenticidad enviado. –

3

Añadir esto en su vista de diseño: app/views/layouts/(something).html.erb

<% if protect_against_forgery? %> 
<script type="text/javascript" charset="utf-8"> 
    //<![CDATA[ 
    window._auth_token_name = "#{request_forgery_protection_token}"; 
    window._auth_token = "#{form_authenticity_token}"; 
    //]]> 
</script> 
<% end %> 

Y en sus application.js:

$.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")} 
}); 

$(document).ready(function() { 
// All non-GET requests will add the authenticity token 
// If not already present in the data packet 
$("body").bind('ajaxSend', function(elm, xhr, s) { 
    if (s.type == "GET") return; 
    if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return; 
    if (s.data) { 
    s.data = s.data + "&"; 
    } else { 
    s.data = ""; 
    // if there was no data, $ didn't set the content-type 
    xhr.setRequestHeader("Content-Type", s.contentType); 
    } 
    s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token); 
}); 

En su application_controller.rb añadir esto a garantizar IE/SAFARI recibir correcta aceptan encabezados:

def correct_safari_and_ie_accept_headers 
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml'] 
     request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr? 
end 

Esto garantiza que el valor predeterminado del encabezado de aceptación sea text/javascript, application/json o text/xml en lugar del text/html predeterminado.

Ahora puede realizar sus llamadas AJAX regulares. Pasará el token de autenticación. También asegúrese de incluir application.js solo después de la etiqueta de script CDATA ya que requiere los dos vars globales window._auth_token_name y window._auth_token.

Espero que esto ayude!Saludos :)

+0

gracias por el código, pero mi problema es que en este momento, mis publicaciones funcionan incluso sin un token de autenticación. –

Cuestiones relacionadas