ruby on rails - authenticity - Rails 4 Autenticidad Token
can''t verify csrf token authenticity (13)
Estaba trabajando en una nueva aplicación de Rails 4 (en Ruby 2.0.0-p0) cuando tuve algunos problemas de token de autenticidad.
Mientras escribía un controlador que responde a json (usando el método respond_to
class), llegué a la acción de create
Comencé a obtener excepciones de ActionController::InvalidAuthenticityToken
cuando intenté crear un registro usando curl
.
Me aseguré de establecer -H "Content-Type: application/json"
y configuré los datos con -d "<my data here>"
pero aún así no -d "<my data here>"
suerte.
Intenté escribir el mismo controlador utilizando Rails 3.2 (en Ruby 1.9.3) y no tuve ningún problema de token de autenticidad. Busqué por todas partes y vi que había algunos cambios con tokens de autenticidad en Rails 4. Por lo que entiendo, ¿ya no se insertan automáticamente en los formularios? Supongo que esto está afectando de alguna manera a los tipos de contenido no HTML.
¿Hay alguna forma de evitar esto sin tener que solicitar un formulario HTML, arrebatando el token de autenticidad y luego haciendo otra solicitud con ese token? ¿O me estoy perdiendo algo que es completamente obvio?
Edición: Acabo de intentar crear un nuevo registro en una nueva aplicación de Rails 4 usando un andamio sin cambiar nada y me estoy topando con el mismo problema, así que supongo que no es algo que hice.
¿Has probado?
protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
Agregando la siguiente línea en el formulario trabajado para mí:
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
Agregue authenticity_token: true
a la etiqueta de formulario
Creo que lo acabo de descubrir. He cambiado el (nuevo) por defecto
protect_from_forgery with: :exception
a
protect_from_forgery with: :null_session
según el comentario en ApplicationController
.
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
Puede ver la diferencia mirando la fuente de request_forgery_protecton.rb
o, más específicamente, las siguientes líneas:
En Rieles 3.2 :
# This is the method that defines the application behavior when a request is found to be unverified.
# By default, /Rails resets the session when it finds an unverified request.
def handle_unverified_request
reset_session
end
En los carriles 4 :
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
Que llamará a lo siguiente :
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
Cuando define su propio formulario html, debe incluir la cadena de token de autenticación, que debe enviarse al controlador por razones de seguridad. Si utiliza el asistente de formulario Rails para generar el token de autenticidad, se agregará al formulario de la siguiente manera.
<form accept-charset="UTF-8" action="/login/signin" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓" />
<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 guías de formularios en lugar de comprometer la seguridad, etc.
En lugar de desactivar la protección csrf, es mejor agregar la siguiente línea de código en el formulario
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
y si está usando form_for o form_tag para generar el formulario, entonces agregará automáticamente la línea de código anterior en el formulario
Encontré el mismo problema. Se corrigió agregando a mi controlador:
skip_before_filter :verify_authenticity_token, if: :json_request?
Esta es una característica de seguridad en Rails. Agregue esta línea de código en el formulario:
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
La documentación se puede encontrar aquí: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
Estas características se agregaron para fines de seguridad y protección contra falsificaciones.
Sin embargo, para responder a su pregunta, aquí hay algunas entradas. Puede agregar estas líneas después de su nombre del controlador.
Al igual que,
class NameController < ApplicationController
skip_before_action :verify_authenticity_token
Aquí hay algunas líneas para diferentes versiones de rieles.
Rieles 3
skip_before_filter: verify_authenticity_token
Rieles 4 :
skip_before_action: verify_authenticity_token
Si pretende deshabilitar esta función de seguridad para todas las rutinas de controlador, puede cambiar el valor de protect_from_forgery a : null_session en su archivo application_controller.rb.
Al igual que,
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
end
Este documento oficial - habla sobre cómo desactivar la protección falsificada para api correctamente http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
No creo que sea bueno desactivar la protección CSRF siempre y cuando no implementes una API exclusivamente.
Al consultar la documentación de la API de Rails 4 para api.rubyonrails.org/classes/ActionController/… , descubrí que puede desactivar la protección falsificada por controlador o por método.
Por ejemplo, para desactivar la protección CSRF para los métodos que puede utilizar
class FooController < ApplicationController
protect_from_forgery except: :index
Si está utilizando jQuery con rieles, tenga cuidado de no permitir la entrada a métodos sin verificar el token de autenticidad.
jquery-ujs puede gestionar los tokens por ti
Ya deberías tenerlo como parte de la gema jquery-rails, pero es posible que tengas que incluirlo en application.js con
//= require jquery_ujs
Eso es todo lo que necesita: su llamada ajax ahora debería funcionar
Para obtener más información, consulte: https://github.com/rails/jquery-ujs
Todas mis pruebas funcionaron bien. Pero por alguna razón había configurado mi variable de entorno como no-test:
export RAILS_ENV=something_non_test
Olvidé desactivar esta variable debido a que comencé a obtener la excepción ActionController::InvalidAuthenticityToken
.
Después de desactivar $RAILS_ENV
, mis pruebas comenzaron a funcionar nuevamente.