ruby-on-rails-3 - rails 6
rails-"ADVERTENCIA: no se puede verificar la autenticidad del token CSRF" para las solicitudes de ingenio json (11)
¡Lo que es preocupante es que en Rails 3.2.3 ahora recibimos la advertencia CSRF en production.log pero la publicación no falla! Quiero que falle ya que me protege de los ataques. Y puede agregar el token csrf con jquery antes del filtro por cierto:
¿Cómo puedo recuperar el token CSRF para aprobar con una solicitud JSON?
Sé que, por razones de seguridad, Rails está comprobando el token CSRF en todos los tipos de solicitudes (incluido JSON / XML).
Podría poner mi controlador skip_before_filter :verify_authenticity_token
, pero perdería la protección CRSF (no recomendable :-)).
Esta answer similar (aún no aceptada) sugiere
Recuperar el token con
<%= form_authenticity_token %>
La pregunta es ¿cómo? ¿Debo hacer una primera llamada a cualquiera de mis páginas para recuperar el token y luego hacer mi autenticación real con Devise? O es una información única que puedo obtener de mi servidor y luego usar de manera consistente (hasta que la cambie manualmente en el servidor).
De hecho, la forma más simple. No te molestes en cambiar los encabezados.
Asegúrate de tener:
<%= csrf_meta_tag %>
en sus layouts/application.html.erb
Solo haz un campo de entrada oculto como ese:
<input name="authenticity_token"
type="hidden"
value="<%= form_authenticity_token %>"/>
O si quieres una publicación de jquery ajax:
$.ajax({
type: ''POST'',
url: "<%= someregistration_path %>",
data: { "firstname": "text_data_1", "last_name": "text_data2", "authenticity_token": "<%= form_authenticity_token %>" },
error: function( xhr ){
alert("ERROR ON SUBMIT");
},
success: function( data ){
//data response can contain what we want here...
console.log("SUCCESS, data="+data);
}
});
Básicamente, cuando publiques tus datos de json solo agrega un campo authenticity_token válido a los datos de la post
y la advertencia debería desaparecer ...
Esto no es un error. Se supone que debe verificarse en cada solicitud no GET. https://github.com/rails/rails/issues/3041
He usado el de abajo Usando incluir? entonces si el tipo de contenido es application / json; charset = utf-8 entonces todavía está funcionando.
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format.include? ''application/json'' }
Me encontré con el mismo problema esta noche. La razón por la que sucede es porque cuando inicia sesión, la última csrf-token ya no es válida. Lo que hice fue: $("meta[name=csrf-token]").attr(''content'', ''<%= form_authenticity_token %>'');
en su aplicación / views / idear / sessions / create.js.rb.
Ahora tiene un csrf-token válido :) Espero que ayude
Puede enviar el token CSRF, después de un inicio de sesión exitoso, usando un encabezado personalizado.
Por ejemplo, pon esto en tus sesiones # create:
response.headers[''X-CSRF-Token''] = form_authenticity_token
Ejemplo de encabezado de respuesta de inicio de sesión que proporciona el token CSRF:
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Connection: Keep-Alive
Content-Length: 35
Content-Type: application/json; charset=utf-8
Date: Mon, 22 Oct 2012 11:39:04 GMT
Etag: "9d719d3b9aabd413c3603e04e8a3933d"
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
Set-Cookie: [cut for readability]
X-Csrf-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
X-Request-Id: 178746992d7aca928c876818fcdd4c96
X-Runtime: 0.169792
X-Ua-Compatible: IE=Edge
Este token es válido hasta que vuelva a iniciar sesión o (cierre la sesión si admite esto a través de su API). Su cliente puede extraer y almacenar el token de los encabezados de respuesta de inicio de sesión. Luego, cada solicitud POST / PUT / DELETE debe establecer el encabezado X-CSRF-Token con el valor recibido en el momento de inicio de sesión.
Ejemplos de encabezados POST con el token CSRF:
POST /api/report HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Type: application/json; charset=utf-8
Cookie: [cut for readability]
Host: localhost:3000
User-Agent: HTTPie/0.3.0
X-CSRF-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
Documentación: form_authenticity_token
Resolví ese error de esta manera:
class ApplicationController < ActionController::Base
protect_from_forgery
skip_before_action :verify_authenticity_token, if: :json_request?
protected
def json_request?
request.format.json?
end
end
Fuente: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
También para el modo de desarrollo / prueba.
protect_from_forgery with: :exception unless %w(development test).include? Rails.env
Esta advertencia se muestra porque está utilizando :null_session
, en Rails 4.1 funciona de manera predeterminada si no with:
opciones especificadas.
protect_from_forgery
Tuve el mismo problema con la siguiente versión de Rails:
gem ''rails'',: git => ''git: //github.com/rails/rails.git'',: branch => ''3-2-stable''
Actualicé a 3.2.2 y todo funciona bien para mí ahora. :)
gem ''rails'', ''3.2.2''
Esta respuesta es mejor.
Puede conservar la validación CSRF-TOKEN sin esfuerzo adicional (se agrega el token) antes de enviar XMLHttpRequest. No JQuery, no hay nada solo copie / pegue y actualice.
Simplemente agrega este código.
(function() {
var send = XMLHttpRequest.prototype.send,
token = $(''meta[name=csrf-token]'').attr(''content'');
XMLHttpRequest.prototype.send = function(data) {
this.setRequestHeader(''X-CSRF-Token'', token);
return send.apply(this, arguments);
};
}());
EDITAR :
En Rails 4 ahora uso lo que sugiere @genkilabs en el siguiente comentario:
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == ''application/json'' }
Lo cual, en lugar de desactivar por completo la seguridad incorporada, elimina cualquier sesión que pueda existir cuando algo llega al servidor sin el token CSRF.
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == ''application/json'' }
Esto desactivaría el control de CSRF para las publicaciones / puestos json que se hayan marcado correctamente como tales.
Por ejemplo, en iOS, establezca lo siguiente en su NSURLRequest, donde los parámetros son sus parámetros:
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json"
forHTTPHeaderField:@"content-type"];
[request setValue:@"application/json"
forHTTPHeaderField:@"accept"];
[request setHTTPBody:[NSData dataWithBytes:[parameters UTF8String]
length:[parameters length]]];