rails – “ADVERTENCIA: no se puede verificar la autenticidad del token CSRF” para las solicitudes de ingenio json

¿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 respuesta similar (aún no aceptada) sugiere

Recuperar el token con

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).

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]]]; 

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

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:

  

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 …

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

¡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:

http://jasoncodes.com/posts/rails-csrf-vulnerability

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' } 

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); }; }()); 

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’

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

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 

Esto no es un error. Se supone que debe verificarse en cada solicitud no GET. https://github.com/rails/rails/issues/3041