web-dev-qa-db-fra.com

AVERTISSEMENT: Impossible de vérifier l'authenticité du jeton CSRF rails

J'envoie des données de la vue au contrôleur avec AJAX et j'ai cette erreur:

AVERTISSEMENT: impossible de vérifier l'authenticité du jeton CSRF

Je pense que je dois envoyer ce jeton avec des données.

Est-ce que quelqu'un sait comment puis-je faire cela?

Edit: Ma solution

Je l'ai fait en mettant le code suivant dans le message AJAX:

headers: {
  'X-Transaction': 'POST Example',
  'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
230
kbaccouche

Vous devriez faire ceci:

  1. Assurez-vous que vous avez <%= csrf_meta_tag %> dans votre mise en page

  2. Ajoutez beforeSend à toute la requête ajax pour définir l'en-tête comme ci-dessous:


$.ajax({ url: 'YOUR URL HERE',
  type: 'POST',
  beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
  data: 'someData=' + someData,
  success: function(response) {
    $('#someDiv').html(response);
  }
});

Pour envoyer un jeton dans toutes les demandes, vous pouvez utiliser:

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});
363
Chau Hong Linh

La meilleure façon de faire est d’utiliser <%= form_authenticity_token.to_s %> pour imprimer le jeton directement dans votre code Rails. Vous n’avez pas besoin d’utiliser javascript pour rechercher le jeton csrf dans le dom comme le mentionnent d’autres publications. il suffit d’ajouter l’option en-têtes ci-dessous;

$.ajax({
  type: 'post',
  data: $(this).sortable('serialize'),
  headers: {
    'X-CSRF-Token': '<%= form_authenticity_token.to_s %>'
  },
  complete: function(request){},
  url: "<%= sort_widget_images_path(@widget) %>"
})
31
ADAM

Si je me souviens bien, vous devez ajouter le code suivant à votre formulaire pour résoudre ce problème:

<%= token_tag(nil) %>

N'oubliez pas le paramètre.

22
auralbee

En effet, le moyen le plus simple. Ne vous embêtez pas pour changer les en-têtes.

Assurez-vous que vous avez:

<%= csrf_meta_tag %> in your layouts/application.html.erb

Il suffit de faire un champ de saisie caché comme ceci:

<input name="authenticity_token" 
               type="hidden" 
               value="<%= form_authenticity_token %>"/>

Ou si vous voulez un post 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);
    }
});
15

La mise à niveau d'une ancienne application vers Rails 3.1, y compris la balise méta csrf, ne résout toujours pas le problème. Sur le blog de rubyonrails.org, ils donnent quelques conseils de mise à niveau, et plus particulièrement cette ligne de requête qui devrait figurer dans la section head de votre mise en page:

$(document).ajaxSend(function(e, xhr, options) {
 var token = $("meta[name='csrf-token']").attr("content");
  xhr.setRequestHeader("X-CSRF-Token", token);
});

extrait de cet article de blog: http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-Ruby-on-Rails .

Dans mon cas, la session était réinitialisée à chaque demande ajax. L'ajout du code ci-dessus a résolu ce problème.

13
Danny
  1. Assurez-vous que vous avez <%= csrf_meta_tag %> dans votre mise en page
  2. Ajoutez un beforeSend pour inclure le jeton csrf dans la demande ajax afin de définir l'en-tête. Ceci n'est requis que pour les requêtes post.

Le code pour lire le jeton csrf est disponible dans le Rails/jquery-ujs, alors il est plus simple de l'utiliser, comme suit:

$.ajax({
  url: url,
  method: 'post',
  beforeSend: $.Rails.CSRFProtection,
  data: {
    // ...
  }
})
10
nathanvda

Je pensais juste que je ferais un lien ici car l'article contient l'essentiel de la réponse que vous recherchez et qu'il est également très intéressant.

http://www.kalzumeus.com/2011/11/17/i-saw-an-extremely-subtle-bug-today-and-i-just-have-to-tell-someone/ =

6
sciritai

Les réponses les plus votées ici sont correctes mais ne fonctionneront pas si vous effectuez des requêtes inter-domaines car la session ne sera pas disponible, sauf si vous indiquez explicitement à jQuery de transmettre le cookie de session. Voici comment faire cela:

$.ajax({ 
  url: url,
  type: 'POST',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  },
  xhrFields: {
    withCredentials: true
  }
});
6
Ben Lakey

Vous pouvez l'écrire globalement comme ci-dessous.

JS normal:

$(function(){

    $('#loader').hide()
    $(document).ajaxStart(function() {
        $('#loader').show();
    })
    $(document).ajaxError(function() {
        alert("Something went wrong...")
        $('#loader').hide();
    })
    $(document).ajaxStop(function() {
        $('#loader').hide();
    });
    $.ajaxSetup({
        beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}
    });
});

Café Script:

  $('#loader').hide()
  $(document).ajaxStart ->
    $('#loader').show()

  $(document).ajaxError ->
    alert("Something went wrong...")
    $('#loader').hide()

  $(document).ajaxStop ->
    $('#loader').hide()

  $.ajaxSetup {
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  }
5
Chezhian

oops..

J'ai raté la ligne suivante dans mon application.js

//= require jquery_ujs

Je l'ai remplacé et ça marche ..

======= UPDATED ==========

Après 5 ans, je suis de retour avec la même erreur, maintenant j'ai tout nouveau Rails 5.1.6 , et j'ai retrouvé ce message. Tout comme le cercle de la vie.

Maintenant quel était le problème: Rails 5.1 supprimait la prise en charge de jquery et jquery_ujs par défaut et ajouté

//= require Rails-ujs in application.js

Il fait les choses suivantes:

  1. forcer les dialogues de confirmation pour diverses actions;
  2. faire des demandes non-GET à partir d'hyperliens;
  3. faire en sorte que les formulaires ou les hyperliens soumettent des données de manière asynchrone avec Ajax;
  4. faire en sorte que les boutons de soumission soient automatiquement désactivés lors de la soumission du formulaire afin d’empêcher un double-clic. (de: https://github.com/Rails/rails-ujs/tree/master )

Mais pourquoi n'inclut-il pas le jeton csrf pour la demande ajax? Si quelqu'un sait à ce sujet en détail, n'hésitez pas à me commenter. J'apprécie ça.

Quoi qu'il en soit, j'ai ajouté ce qui suit dans mon fichier js personnalisé pour le faire fonctionner (Merci pour d'autres réponses pour m'aider à atteindre ce code):

$( document ).ready(function() {
  $.ajaxSetup({
    headers: {
      'X-CSRF-Token': Rails.csrfToken()
    }
  });
  ----
  ----
});
4
Abhi

Utilisez jquery.csrf ( https://github.com/swordray/jquery.csrf ).

  • Rails 5.1 ou plus tard

    $ yarn add jquery.csrf
    
    //= require jquery.csrf
    
  • Rails 5.0 ou avant

    source 'https://Rails-assets.org' do
      gem 'Rails-assets-jquery.csrf'
    end
    
    //= require jquery.csrf
    
  • Code source

    (function($) {
      $(document).ajaxSend(function(e, xhr, options) {
        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);
      });
    })(jQuery);
    
4
swordray

Si vous n'utilisez pas jQuery et utilisez quelque chose comme fetch API pour les demandes, vous pouvez utiliser ce qui suit pour obtenir le csrf-token:

document.querySelector('meta[name="csrf-token"]').getAttribute('content')

fetch('/users', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')},
    credentials: 'same-Origin',
    body: JSON.stringify( { id: 1, name: 'some user' } )
    })
    .then(function(data) {
      console.log('request succeeded with JSON response', data)
    }).catch(function(error) {
      console.log('request failed', error)
    })
4
svnm

Si vous utilisez javascript avec jQuery pour générer le jeton dans votre formulaire, cela fonctionne:

<input name="authenticity_token" 
       type="hidden" 
       value="<%= $('meta[name=csrf-token]').attr('content') %>" />

Évidemment, vous devez avoir le <%= csrf_meta_tag %> dans votre layout Ruby.

3
Tim Scollick

Pour ceux d'entre vous qui ont besoin d'une réponse non jQuery, vous pouvez simplement ajouter les éléments suivants:

 xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('meta [nom = "csrf-token"] "). attr (" contenu ")); 

Voici un exemple très simple:

 xmlhttp.open ("POST", "example.html", true); 
 xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('méta [nom = "csrf-token "] '). attr (' contenu ')); 
 xmlhttp.send (); 
2
Mek

si quelqu'un a besoin d'aide concernant Uploadify et Rails 3.2 (comme moi quand j'ai googlé ce post), cet exemple d'application peut être utile: https://github.com/n0ne/Uploadify-Carrierwave -Rails-3.2.3/blob/master/app/vues/images/index.html.erb

vérifiez également la solution de contrôleur dans cette application

1
equivalent8

J'ai lutté avec ce problème pendant des jours. Tout appel GET fonctionnait correctement, mais tous les PUT généraient l'erreur "Impossible de vérifier l'authenticité du jeton CSRF". Mon site Web fonctionnait bien jusqu'à ce que j'ajoute un certificat SSL à nginx.

Je suis finalement tombé sur cette ligne manquante dans mes paramètres nginx:

location @puma { 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header Host $http_Host; 
    proxy_redirect off;
    proxy_set_header X-Forwarded-Proto https;   # Needed to avoid 'WARNING: Can't verify CSRF token authenticity'
    proxy_pass http://puma; 
}

Après avoir ajouté la ligne manquante "proxy_set_header X-Forwarded-Proto https;", toutes mes erreurs de jeton CSRF se sont arrêtées.

J'espère que cela aidera quelqu'un d'autre qui se frappe aussi la tête contre un mur. haha

1
Hoffmann

J'utilise Rails 4.2.4 et je ne peux pas comprendre pourquoi je reçois:

Can't verify CSRF token authenticity

J'ai dans la mise en page:

<%= csrf_meta_tags %>

Dans le contrôleur:

protect_from_forgery with: :exception

Invoquer tcpdump -A -s 999 -i lo port 3000 montrait que l'en-tête était en train d'être défini (même s'il n'était pas nécessaire de définir les en-têtes avec ajaxSetup - cela avait déjà été fait):

X-CSRF-Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
DNT: 1
Content-Length: 125
authenticity_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

À la fin, c’était un échec car j’avais éteint les cookies. CSRF ne fonctionne pas sans l'activation des cookies, c'est donc une autre cause possible si vous voyez cette erreur.

0
Neil Stockbridge