Sé que esto se ha mencionado varias veces en SO, pero no puedo avanzar. Estoy en Rails 5.0.7.2.
Recibo ActionController::InvalidCrossOriginRequest lanzado cientos de veces al día. Rollbar dice que es principalmente causado por Bingbot, y está en mi modo de registro de usuario, que es de Devise. Es una solicitud GET y la ruta es /users/sign_up .
NOTA: No es un formulario. Es un modal que simplemente pregunta al usuario ¿Cómo te gustaría registrarte? Correo electrónico, Facebook, autenticación de Google, etc.
Básicamente, tengo algunas acciones de javascript en mi sitio, una imagen como un voto a favor de reddit o stackoverflow. No estoy usando remote: true en esos enlaces, sino que tengo una llamada $.ajax que maneja el voto a favor así:
var token = document.querySelector('meta[name="csrf-token"]').content; $.ajax({ // For the upvote, type will be POST type: $this.data('method'), beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-Token', token) }, url: $this.data('url'), success: function(data) { // Some cleanup... } });Una vez que un visitante desconectado intenta votar, activa la solicitud ajax que luego se detiene (no está autorizada) y se redirige, así:
Started POST "/upvotes/toggle_vote" Processing by UpvotesController#toggle_vote as */* Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms) Started GET "/users/sign_up" Processing by RegistrationsController#new as */*Aquí está el controlador Devise que he sobrescrito:
class RegistrationsController < Devise::RegistrationsController def new # ... other code respond_to do |format| format.js { render layout: false } format.html { respond_with self.resource } end end end Dentro de /views/devise/registrations tengo new.js.erb que abre el "¿cómo le gustaría registrarse?" modal.
LO QUE HE PROBADO:
No creo que resolverlo agregando protect_from_forgery except: :new es la respuesta correcta (como se ha propuesto en preguntas similares), ya que eso no es inherentemente seguro.
Intenté reordenar los formatos respond_to segúnesto , pero eso hace que el modal de registro no se abra.
Traté de lanzar un format.any { raise ActionController::RoutingError.new("Not Found") } catch-all en el bloque respond_to pero eso no hizo nada para corregir el error.
Como puede ver en la llamada $.ajax anterior, incluso intento configurar el encabezado X-CSRF-Token .
Por cierto, el texto de error completo es este:
ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript
¿Algunas ideas?
¿Podría ser que el token de autenticidad se esté perdiendo porque UpvotesController#toggle_vote redirige a RegistrationsController#new y cambia de POST a GET?
Debe enviar un token de autenticidad con solicitudes ajax que modifican los recursos en el servidor (post/put/patch/delete). Por lo general, Rails lo agrega como un campo oculto en el formulario.
Me parece un problema de CORS, al igual que el error sugiere que hice una llamada API desde un javascript incrustado que está en un dominio diferente al definido en su servidor. Esto desencadena un error CORS. Por lo general, para corregir el error de CORS, debe agregar un encabezado Access-Control-Allow-Origin con el dominio del sitio web en la lista de dominios permitidos. Puede hacer esto fácilmente con la gema rack cors: https://github.com/cyu/rack-cors
Agregar esto dentro de su formulario debería hacer el truco:
<% hidden_field_tag :authenticity_token, form_authenticity_token %>Un par de pensamientos:
No debe colocar el token csrf usted mismo, tanto jquery-rails como rails-ujs (no estoy seguro de cuál está usando) lo hacen por usted; con rails-ujs necesitas usar el método Rails.ajax
No se puede redirigir POST a GET y mantener los encabezados POST originales , lo que significa que de hecho pierde el token csrf en la solicitud GET (sin embargo, por lo general, no envía ni necesita un token CSRF en una solicitud GET de todos modos, así que verifique por qué lo está haciendo). quizás).