198 votes

Jeton d'authenticité Rails 4

Je travaillais sur une nouvelle application Rails 4 (sur Ruby 2.0.0-p0) lorsque j'ai rencontré des problèmes de jetons d'authenticité.

Lors de l'écriture d'un contrôleur qui répond à json (en utilisant la fonction respond_to ), je suis arrivé à la méthode de la classe create action j'ai commencé à avoir ActionController::InvalidAuthenticityToken exceptions lorsque j'ai essayé de créer un enregistrement en utilisant curl .

Je me suis assuré de mettre -H "Content-Type: application/json" et j'ai défini les données avec -d "<my data here>" mais toujours pas de chance.

J'ai essayé d'écrire le même contrôleur avec Rails 3.2 (sous Ruby 1.9.3) et je n'ai eu aucun problème de jeton d'authenticité. J'ai fait des recherches et j'ai vu qu'il y avait eu quelques changements avec les jetons d'authenticité dans Rails 4. D'après ce que j'ai compris, ils ne sont plus insérés automatiquement dans les formulaires ? Je suppose que cela affecte d'une certaine manière les types de contenu non-HTML.

Existe-t-il un moyen de contourner ce problème sans avoir à demander un formulaire HTML, à récupérer le jeton d'authenticité, puis à faire une autre demande avec ce jeton ? Ou bien est-ce que je passe complètement à côté de quelque chose de tout à fait évident ?

Editar: Je viens d'essayer de créer un nouvel enregistrement dans une nouvelle application Rails 4 en utilisant un scaffold sans rien changer et je rencontre le même problème, donc je suppose que ce n'est pas quelque chose que j'ai fait.

275voto

alexcoco Points 2747

Je crois que je viens de trouver la solution. J'ai changé la (nouvelle) valeur par défaut

protect_from_forgery with: :exception

à

protect_from_forgery with: :null_session

selon le commentaire dans ApplicationController .

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

Vous pouvez voir la différence en regardant la source pour request_forgery_protecton.rb ou, plus précisément, les lignes suivantes :

En Rails 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 Rails 4 :

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

Qui appellera les éléments suivants :

def handle_unverified_request
  raise ActionController::InvalidAuthenticityToken
end

71voto

enchante Points 730

Au lieu de désactiver la protection csrf, il est préférable d'ajouter la ligne de code suivante dans le formulaire

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

et si vous utilisez form_for ou form_tag pour générer le formulaire, alors il ajoutera automatiquement la ligne de code ci-dessus dans le formulaire

70voto

Carlos Points 156

L'ajout de la ligne suivante dans le formulaire a fonctionné pour moi :

<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>

33voto

roamingthings Points 89

Je ne pense pas qu'il soit bon de désactiver de manière générale la protection csrf tant que vous n'implémentez pas exclusivement une API.

En regardant la documentation de l'API Rails 4 pour Contrôleur d'action J'ai découvert que vous pouvez désactiver la protection contre la falsification sur une base par contrôleur ou par méthode.

Par exemple pour désactiver la protection csrf pour les méthodes vous pouvez utiliser

class FooController < ApplicationController
  protect_from_forgery except: :index

0voto

amjad Points 472

Lorsque vous définissez votre propre formulaire html, vous devez inclure la chaîne du jeton d'authentification, qui doit être envoyée au contrôleur pour des raisons de sécurité. Si vous utilisez l'aide de formulaire de rails pour générer le jeton d'authenticité est ajouté au formulaire comme suit.

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

La solution au problème est donc soit d'ajouter le champ authenticity_token, soit d'utiliser les aides de formulaire de rails plutôt que de compromettre la sécurité, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X