ActionController :: InvalidAuthenticityToken

148

A continuación se muestra un error, causado por un formulario en mi aplicación Rails:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Esto sucede para cada no getsolicitud y, como puede ver, authenticity_tokenestá ahí.

Nikita Rybak
fuente

Respuestas:

207

Tuve el mismo problema pero con páginas que fueron almacenadas en caché. Las páginas se almacenaron con un token de autenticidad obsoleto y todas las acciones que utilizan los métodos post / put / delete se reconocieron como intentos de falsificación. Se devolvió el error (422 Entidad no procesable) al usuario.

La solución para Rails 3:
Agregar:

 skip_before_filter :verify_authenticity_token  

o como "sagivo" señaló en Rails 4 agregar:

 skip_before_action :verify_authenticity_token

En páginas que hacen caché.

Como se ha comentado @toobulkeh esto no es una vulnerabilidad en :index, :showacciones, pero cuidado con el uso de este sobre :put, :postacciones.

Por ejemplo:

 caches_page :index, :show  
 skip_before_filter :verify_authenticity_token, :only => [:index, :show]

Referencia: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

Nota agregada por barlop- Rails 4.2 desaprobó skip_before_filter a favor de skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "La familia de métodos * _filter se ha eliminado de la documentación. Su uso se desaconseja a favor de la acción * _ familia de métodos "

Para Rails 6 (como señaló "collimarco") puede usar skip_forgery_protectiony es seguro usarlo para una API REST que no usa datos de sesión.

Szymon Jeż
fuente
3
Ese no es el caso, no sabía de caches_page antes de tu publicación. Pero revisaré caches_page , gracias.
Nikita Rybak
77
en rieles 4skip_before_action :verify_authenticity_token
Sagiv Ofek
88
¿No es esto una vulnerabilidad?
quantumpotato
66
Esto no es una vulnerabilidad en las :index, :showacciones. ¡Pero ten cuidado de poner esto en :put, :postacciones!
toobulkeh
14
aunque estoy de acuerdo en que a veces hay casos en los que esto es necesario (como tal vez una vez en la vida) pero debes darte cuenta de que estás arreglando la seguridad al deshabilitar la seguridad. No recomendado
equivalente8
77

Para mí, la causa de este problema en Rails 4 era una falta,

<%= csrf_meta_tags %>

Línea en el diseño de mi aplicación principal. Lo borré accidentalmente cuando reescribí mi diseño.

Si esto no está en el diseño principal, lo necesitará en cualquier página en la que desee un token CSRF.

James McMahon
fuente
2
También estamos recibiendo este error. Pero es intermitente. ¿Podría ser esta la razón o no tener esto afectaría cada solicitud con un error?
Ryan-Neal Mes
@ Ryan-NealMes, si su plantilla no tiene esa línea, obtendrá el error. Por lo tanto, es posible que algunas de sus plantillas lo tengan y las otras no.
James McMahon
1
@JamesMcMahon gracias, descubrí que mi caso en realidad es causado por usuarios que borran sus cookies o las bloquean. Aprendí mucho de esta pregunta!
Ryan-Neal Mes
61

Hay varias causas para este error (en relación con Rails 4).

1. Verifique el <%= csrf_meta_tags %>presente en el diseño de la página

2. verifique que el token de autenticidad se envíe con llamadas AJAX si usa form_forayuda con la remote: trueopción. Si no, puede incluir la línea <%= hidden_field_tag :authenticity_token, form_authenticity_token %>dentro del bloque de formulario.

3. Si la solicitud se envía desde la página en caché, utilice el almacenamiento en caché de fragmentos para excluir parte de la página que envía la solicitud, por ejemplo, button_toetc., de lo contrario, el token será obsoleto / inválido.

Sería reacio a anular la protección de csrf ...

GoodViber
fuente
csrf_meta_tags debería estar en <head>? ¿Cómo puedo estar seguro de que no entra en conflicto con los enlaces turbo?
brillo
37

Solo agregar el authenticity_tokenformulario lo arregló para mí.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
Deepak Mahakale
fuente
3
Se supone que los rieles envían el token por defecto. No queremos especificarlo explícitamente. Siento que el token ha cambiado de alguna manera en esta situación aquí.
Abhi
1
Sin embargo, si ha creado su formulario sin usar ayudantes, debe ponerlo manualmente.
André Guimarães Sakata
30

El token de autenticidad es un valor aleatorio generado en su opinión para probar que una solicitud se envía desde un formulario en su sitio, no en otro lugar. Esto protege contra los ataques CSRF:

http://en.wikipedia.org/wiki/Cross-site_request_forgery

Verifique quién es ese cliente / IP, parece que están usando su sitio sin cargar sus vistas.

Si necesita depurar más, esta pregunta es un buen lugar para comenzar: Comprender el token de autenticidad de Rails

Editado para explicar: significa que están llamando a la acción para procesar el envío de su formulario sin tener que mostrar su formulario en su sitio web. Esto podría ser malicioso (por ejemplo, publicar comentarios de spam) o podría indicar que un cliente está tratando de usar su API de servicio web directamente. Usted es el único que puede responder eso por la naturaleza de su producto y analizar sus solicitudes.

Winfield
fuente
1
Gracias, pero ya sé qué es el token de autenticidad. Verifique quién es ese cliente / IP, parece que están usando su sitio sin cargar sus vistas. Lo sentimos, ¿qué significa "sin cargar vistas"?
Nikita Rybak
1
Quiero decir que alguien (probablemente un spammer) podría estar enviando datos a su formulario sin pasar por la interfaz de usuario de su aplicación. Es posible hacer esto usando un programa de línea de comandos como curl, por ejemplo.
John Topley
John lo tiene exactamente bien. Significa que están llamando a la acción para procesar el envío de su formulario sin tener que presentar su formulario en su sitio web. Esto podría ser malicioso (por ejemplo, publicar comentarios de spam) o podría indicar que un cliente está tratando de usar su API de servicio web directamente. Usted es el único que puede responder eso por la naturaleza de su producto y analizar sus solicitudes.
Winfield
Ok, entendí mal el comentario de Winfield. Pensé que la aplicación no estaba configurada de alguna manera para 'cargar mis vistas' cuando uso el navegador.
Nikita Rybak
1
También tuve otro pensamiento, estas solicitudes incluyen un token, pero no es válido. Esto podría deberse al almacenamiento en caché de la página que representa su formulario o algo más que causa una posible versión obsoleta del formulario.
Winfield
27

ActionController::InvalidAuthenticityTokenTambién puede ser causado por un proxy inverso mal configurado. Este es el caso si en el seguimiento de la pila, aparece una línea similar Request origin does not match request base_url.

Cuando se usa un proxy inverso (como nginx) como receptor para la solicitud HTTPS y se transmite la solicitud sin cifrar al backend (como la aplicación Rails), el backend (más específicamente: Rack) espera algunos encabezados con más información sobre la solicitud original del cliente para poder aplicar diversas tareas de procesamiento y medidas de seguridad.

Más detalles están disponibles aquí: https://github.com/rails/rails/issues/22965 .

TL; DR: la solución es agregar algunos encabezados:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}
vmarquet
fuente
Wow, he estado buscando durante 3 horas una solución para esto, y esto fue todo, ¡gracias!
evexoio
muchas gracias 6 horas de tratar de resolver esto en los carriles laterales
Joe mitad de la cara
18

Demasiado tarde para responder pero encontré la solución.

Cuando define su propio formulario html, pierde la cadena de token de autenticación que debe enviarse al controlador por razones de seguridad. Pero cuando usas rails form helper para generar un formulario, obtienes algo como seguir

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;">
    <input name="authenticity_token" type="hidden" 
      value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
    .
    .
    .
  </div>
</form>

Por lo tanto, la solución al problema es agregar el campo authenticity_token o usar rails para ayudar en lugar de eliminar, degradar o actualizar rails.

amjad
fuente
9

Si ha realizado un cambio rake rails:updateo lo ha cambiado recientemente config/initializers/session_store.rb, esto puede ser un síntoma de cookies antiguas en el navegador. Esperemos que esto se haga en dev / test (fue para mí), y puede borrar todas las cookies del navegador relacionadas con el dominio en cuestión.

Si esto está en producción y usted cambió key, considere volver a cambiarlo para usar las cookies antiguas (<- solo especulación).

kross
fuente
¡Si! Para mí, tener un session_store.rb vacío estaba causando el error.
LaFeber
6

Tuve este problema con las llamadas de JavaScript. Lo arreglé con solo requerir jquery_ujs en el archivo application.js.

Michael Koper
fuente
Sí, correcto, también tuve este problema y agregué jquery_ujs en la aplicación js. Funcionó.
Abhi
3

Tuvimos el mismo problema, pero notamos que era solo para solicitudes usando http: // y no con https: //. La causa fue secure: truepara session_store:

Rails.application.config.session_store(
  :cookie_store,
  key: '_foo_session',
  domain: '.example.com',
  secure: true
)

Solucionado mediante el uso de HTTPS ~ en todas partes :)

Darep
fuente
Encontré esto cuando uso rails s(no SSL) en lugar del punto final SSL que he configurado para el desarrollo. No fue hasta que leí tu comentario que me di cuenta de lo que estaba haciendo. Una vez que volví a usar SSL, las cosas comenzaron a funcionar nuevamente. ¡Gracias!
Karl Wilbur
1
Enfrenté este problema en el desarrollo. En lugar de lo secure: trueque escribísecure: !Rails.env.development?
murb
1

Para los rieles 5, es mejor agregar protect_from_forgery prepend: trueque omitirverify_authentication_token

aadeshere1
fuente
55
¿Por qué? ¿Podría agregar una referencia?
kwerle
1

Añadir

//= require rails-ujs 

en

\app\assets\javascripts\application.js
Maicon Douglas
fuente
0

Tuve este problema y la razón fue porque copié y pegué un controlador en mi aplicación. Necesitaba cambiar ApplicationControlleraApplicationController::Base

usuario2954587
fuente
0

Tuve el mismo problema en localhost. He cambiado el dominio de la aplicación, pero en las URL y el archivo de hosts todavía existía el dominio anterior. Actualicé los marcadores de mi navegador y el archivo de hosts para usar un nuevo dominio y ahora todo funciona bien.

Modificación
fuente
0

¿Quizás tiene su configuración NGINX para HTTPS pero sus certificados no son válidos? Tuve un problema similar en el pasado y la redirección de http a https resolvió el problema

montrealmike
fuente
0

He comprobado que los <% = csrf_meta_tags%> están presentes y la eliminación de cookies en el navegador funcionó para mí.

Praveen KJ
fuente
0

Siguiendo las recomendaciones de Chrome Lighthouse para una carga de aplicaciones más rápida, he asycedido mi Javascript:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

Esto rompió todo y obtuvo ese error de token para mis formularios remotos. La eliminación async: truesolucionó el problema.

Maxence
fuente
0

Esta respuesta es mucho más específica para Ruby on Rails, pero con suerte ayudará a alguien.

Debe incluir el token CSRF con cada solicitud que no sea GET. Si está acostumbrado a usar JQuery, Rails tiene una biblioteca auxiliar llamada jquery-ujsque se construye encima y agrega algunas funciones ocultas. Una de las cosas que hace es incluir automáticamente el token CSRF en cada ajaxsolicitud. Vea aquí .

Si te alejas de él como lo hice, es posible que te encuentres con un error. Puede enviar el token manualmente o usar otra biblioteca para ayudar a eliminar el token del DOM. Vea esta publicación para más detalles.

usuario2490003
fuente
0

Para el entorno de desarrollo, probé muchos de estos intentos para solucionar este problema, en Rails 6. Ninguno de ellos ayudó. Entonces, si ninguna de estas sugerencias funcionó para usted, intente a continuación.

La única solución que encontré fue agregar un archivo txt a su carpeta / tmp.

En el directorio raíz de su aplicación, ejecute:

touch tmp/caching-dev.txt

O cree manualmente un archivo con ese nombre en su carpeta / tmp. Como esto me lo solucionó, supongo que la raíz del problema es un conflicto de almacenamiento en caché.

Twistedben
fuente
-1

En los rieles 5, necesitamos agregar 2 líneas de código

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception
giapnh
fuente
-2

Instalando

gem 'remotipart' 

poder ayudar

Alexei.B
fuente
3
aunque esta podría ser la respuesta, pero también es útil incluir la parte esencial de la respuesta y explicar por qué / cómo funciona.
Roy Lee
-15

Problema resuelto bajando a 2.3.5 desde 2.3.8. (así como el infame problema de 'Estás siendo redirigido')

Nikita Rybak
fuente
@Flip tal vez es una idea actualizar la respuesta aceptada?
Lafeber