ActionController :: InvalidAuthenticityToken

148

Unten ist ein Fehler aufgeführt, der durch ein Formular in meiner Rails-Anwendung verursacht wurde:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Dies geschieht für jede Nichtanforderung getund ist, wie Sie sehen, authenticity_tokenvorhanden.

Nikita Rybak
quelle

Antworten:

207

Ich hatte das gleiche Problem, aber mit Seiten, die zwischengespeichert wurden. Die Seiten wurden mit einem veralteten Authentizitätstoken gepuffert, und alle Aktionen mit den Methoden post / put / delete wurden als Fälschungsversuche erkannt. Der Fehler (422 Unprocessable Entity) wurde an den Benutzer zurückgegeben.

Die Lösung für Rails 3:
Hinzufügen:

 skip_before_filter :verify_authenticity_token  

oder als "sagivo" in Rails 4 hervorgehoben:

 skip_before_action :verify_authenticity_token

Auf Seiten, die Caching durchführen.

Wie @toobulkeh kommentierte dies ist keine Schwachstelle auf :index, :showAktionen, aber mit diesem auf Vorsicht :put, :postAktionen.

Beispielsweise:

 caches_page :index, :show  
 skip_before_filter :verify_authenticity_token, :only => [:index, :show]

Referenz: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

Hinweis hinzugefügt von barlop-Rails 4.2 veralteter skip_before_filter zugunsten von skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "Die * _filter-Methodenfamilie wurde aus der Dokumentation entfernt. Von ihrer Verwendung wird zugunsten der * _action abgeraten Methodenfamilie "

Für Rails 6 (wie "collimarco" hervorhob) können Sie es verwenden skip_forgery_protectionund es ist sicher, es für eine REST-API zu verwenden, die keine Sitzungsdaten verwendet.

Szymon Jeż
quelle
3
Das ist wahrscheinlich nicht der Fall, ich wusste vor Ihrem Beitrag nichts von caches_page . Aber ich werde caches_page überprüfen , danke.
Nikita Rybak
7
in Schienen 4skip_before_action :verify_authenticity_token
Sagiv Ofek
88
Ist das nicht eine Schwachstelle?
Quantumpotato
6
Dies ist keine Sicherheitslücke bei :index, :showAktionen. Aber seien Sie vorsichtig, wenn Sie dies in die :put, :postTat umsetzen!
Toobulkeh
14
Ich stimme zwar zu, dass Sie manchmal Fälle haben, in denen dies erforderlich ist (wie vielleicht einmal im Leben), aber Sie müssen erkennen, dass Sie die Sicherheit beheben, indem Sie die Sicherheit deaktivieren. Nicht empfohlen
Äquivalent8
77

Für mich fehlte die Ursache für dieses Problem unter Rails 4,

<%= csrf_meta_tags %>

Zeile in meinem Hauptanwendungslayout. Ich hatte es versehentlich gelöscht, als ich mein Layout neu schrieb.

Wenn dies nicht im Hauptlayout enthalten ist, benötigen Sie es auf jeder Seite, auf der Sie ein CSRF-Token möchten.

James McMahon
quelle
2
Wir erhalten auch diesen Fehler. Aber es ist unterbrochen. Könnte dies der Grund sein oder würde dies nicht jede Anfrage mit einem Fehler betreffen?
Ryan-Neal Mes
@ Ryan-NealMes, wenn Ihre Vorlage diese Zeile fehlt, erhalten Sie den Fehler. Es ist also möglich, dass einige Ihrer Vorlagen es haben und die anderen nicht.
James McMahon
1
@ JamesMcMahon danke, ich habe herausgefunden, dass mein Fall tatsächlich dadurch verursacht wird, dass Benutzer ihre Cookies löschen oder Cookies blockieren lassen. Aus dieser Frage viel gelernt!
Ryan-Neal Mes
61

Es gibt verschiedene Ursachen für diesen Fehler (in Bezug auf Schienen 4).

1. Überprüfen Sie das <%= csrf_meta_tags %>Vorhandensein im Seitenlayout.

2. Überprüfen Sie, ob bei AJAX-Aufrufen ein Authentizitätstoken gesendet wird, wenn Sie den form_forHelfer mit remote: trueOption verwenden. Wenn nicht, können Sie die Zeile <%= hidden_field_tag :authenticity_token, form_authenticity_token %>mit dem Formularblock einfügen.

3. Wenn eine Anfrage von einer zwischengespeicherten Seite gesendet wird, verwenden Sie das Fragment-Caching , um einen Teil der Seite auszuschließen, die eine Anfrage sendet, z button_to. B. usw. Andernfalls ist das Token veraltet / ungültig.

Ich würde den CSR-Schutz nur ungern aufheben ...

GoodViber
quelle
csrf_meta_tags sollte in <head> sein? Wie kann ich sicher sein, dass es nicht zu Konflikten mit Turbolinks kommt?
funkeln
37

Nur das Hinzufügen des authenticity_tokenIn-Formulars hat es für mich behoben.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
Deepak Mahakale
quelle
3
Schienen sollen das Token standardmäßig senden. Wir wollen es nicht explizit spezifizieren. Ich habe das Gefühl, dass sich das Token in dieser Situation hier irgendwie geändert hat.
Abhi
1
Wenn Sie Ihr Formular jedoch ohne Hilfe erstellt haben, sollten Sie es manuell einfügen.
André Guimarães Sakata
30

Das Authentizitätstoken ist ein zufälliger Wert, der aus Ihrer Sicht generiert wird, um zu beweisen, dass eine Anfrage von einem Formular auf Ihrer Website gesendet wurde, nicht von einem anderen Ort. Dies schützt vor CSRF-Angriffen:

http://en.wikipedia.org/wiki/Cross-site_request_forgery

Überprüfen Sie, wer dieser Client / diese IP ist. Es sieht so aus, als würden sie Ihre Site verwenden, ohne Ihre Ansichten zu laden.

Wenn Sie weiter debuggen müssen, ist diese Frage ein guter Ausgangspunkt: Grundlegendes zum Rails-Authentizitätstoken

Zur Erklärung bearbeitet: Dies bedeutet, dass sie die Aktion zum Verarbeiten Ihres Formulars aufrufen, ohne Ihr Formular jemals auf Ihrer Website zu rendern. Dies kann böswillig sein (z. B. das Versenden von Spam-Kommentaren) oder auf einen Kunden hinweisen, der versucht, Ihre Webdienst-API direkt zu verwenden. Sie sind der einzige, der dies anhand der Art Ihres Produkts und der Analyse Ihrer Anfragen beantworten kann.

Winfield
quelle
1
Danke, aber ich weiß bereits, was Authentizitätstoken ist. Überprüfen Sie, wer dieser Client / diese IP ist. Es sieht so aus, als würden sie Ihre Site verwenden, ohne Ihre Ansichten zu laden. Entschuldigung, was bedeutet "ohne Ansichten zu laden"?
Nikita Rybak
1
Ich meine, dass jemand (wahrscheinlich ein Spammer) Daten an Ihr Formular senden könnte, ohne die Benutzeroberfläche Ihrer Anwendung zu durchlaufen. Dies ist mit einem Befehlszeilenprogramm wie beispielsweise curl möglich.
John Topley
John hat es genau richtig. Dies bedeutet, dass sie die Aktion zum Verarbeiten Ihres Formulars aufrufen, ohne Ihr Formular jemals auf Ihrer Website zu rendern. Dies kann böswillig sein (z. B. das Versenden von Spam-Kommentaren) oder auf einen Kunden hinweisen, der versucht, Ihre Webdienst-API direkt zu verwenden. Sie sind der einzige, der dies anhand der Art Ihres Produkts und der Analyse Ihrer Anfragen beantworten kann.
Winfield
Ok, ich habe Winfields Kommentar falsch verstanden. Ich dachte, die App sei nicht so konfiguriert, dass sie meine Ansichten lädt, wenn ich einen Browser verwende.
Nikita Rybak
1
Ich hatte auch einen anderen Gedanken, diese Anfragen enthalten ein Token, aber es ist nicht gültig. Dies kann durch das Zwischenspeichern der Seite, auf der Ihr Formular gerendert wird, oder durch etwas anderes verursacht werden, das möglicherweise eine veraltete Version des Formulars verursacht.
Winfield
26

ActionController::InvalidAuthenticityTokenkann auch durch einen falsch konfigurierten Reverse-Proxy verursacht werden. Dies ist der Fall, wenn in der Stapelverfolgung eine Linie angezeigt wird Request origin does not match request base_url.

Wenn Sie einen Reverse-Proxy (z. B. nginx) als Empfänger für eine HTTPS-Anforderung verwenden und die Anforderung unverschlüsselt an das Backend (z. B. die Rails-App) senden, erwartet das Backend (genauer gesagt: Rack) einige Header mit mehr Informationen zur ursprünglichen Clientanforderung um verschiedene Verarbeitungsaufgaben und Sicherheitsmaßnahmen anwenden zu können.

Weitere Details finden Sie hier: https://github.com/rails/rails/issues/22965 .

TL; DR: Die Lösung besteht darin, einige Header hinzuzufügen:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}
vmarquet
quelle
Wow, ich habe 3 Stunden nach einer Lösung dafür gesucht, und das war es, danke!
Evexoio
Vielen Dank 6 Stunden Versuch, dies auf der Schienenseite zu lösen
Joe Half Face
18

Zu spät, um zu antworten, aber ich habe die Lösung gefunden.

Wenn Sie Ihr eigenes HTML-Formular definieren, fehlt eine Authentifizierungs-Token-Zeichenfolge, die aus Sicherheitsgründen an den Controller gesendet werden sollte. Wenn Sie jedoch Rails Form Helper verwenden, um ein Formular zu generieren, erhalten Sie so etwas wie Folgendes

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

Die Lösung des Problems besteht also darin, entweder das Feld authenticity_token hinzuzufügen oder Schienen von Hilfsprogrammen zu verwenden, anstatt Schienen zu entfernen, herunterzustufen oder zu aktualisieren.

amjad
quelle
9

Wenn Sie eine rake rails:updateoder eine andere kürzlich vorgenommene Änderung vorgenommen habenconfig/initializers/session_store.rb , ist dies möglicherweise ein Symptom für alte Cookies im Browser. Hoffentlich geschieht dies in dev / test (es war für mich), und Sie können einfach alle Browser-Cookies löschen, die sich auf die betreffende Domain beziehen.

Wenn dies in Produktion ist und Sie es geändert haben key, sollten Sie es zurücksetzen, um die alten Cookies zu verwenden (<- nur Spekulation).

kross
quelle
Ja! Für mich verursachte eine leere session_store.rb den Fehler.
Lafeber
6

Ich hatte dieses Problem mit Javascript-Aufrufen. Ich habe das behoben, indem ich nur jquery_ujs in die Datei application.js benötigte.

Michael Koper
quelle
Ja richtig, ich hatte auch dieses Problem und habe jquery_ujs in Anwendung js hinzugefügt. Es funktionierte.
Abhi
3

Wir hatten das gleiche Problem, stellten jedoch fest, dass es sich nur um Anfragen mit http: // und nicht mit https: // handelte. Die Ursache war secure: truefür session_store:

Rails.application.config.session_store(
  :cookie_store,
  key: '_foo_session',
  domain: '.example.com',
  secure: true
)

Behoben durch Verwendung von HTTPS ~ überall :)

Darep
quelle
Dies ist mir bei der Verwendung von rails s(Nicht-SSL) anstelle des SSL-Endpunkts begegnet, den ich für die Entwicklung eingerichtet habe. Erst als ich Ihren Kommentar las, wurde mir klar, was ich tat. Nachdem ich wieder SSL verwendet hatte, funktionierten die Dinge wieder. Vielen Dank!
Karl Wilbur
1
Ich habe mich in der Entwicklung mit diesem Problem befasst. Anstelle von secure: trueschrieb ichsecure: !Rails.env.development?
Murb
1

Für Schienen 5 ist es besser, die hinzuzufügen, protect_from_forgery prepend: trueals die zu überspringenverify_authentication_token

aadeshere1
quelle
5
Warum? Könnten Sie eine Referenz hinzufügen?
Kwerle
1

Hinzufügen

//= require rails-ujs 

im

\app\assets\javascripts\application.js
Maicon Douglas
quelle
0

Ich hatte dieses Problem und der Grund war, dass ich einen Controller kopiert und in meine App eingefügt habe. Ich musste ändern ApplicationControllerzuApplicationController::Base

user2954587
quelle
0

Ich hatte das gleiche Problem bei localhost. Ich habe die Domain für die App geändert, aber in der URL- und Hosts-Datei befand sich noch die alte Domain. Die Lesezeichen und die Hosts-Datei meines Browsers wurden aktualisiert, um eine neue Domain zu verwenden. Jetzt funktioniert alles einwandfrei.

MoD
quelle
0

Vielleicht haben Sie Ihr NGINX-Setup für HTTPS, aber Ihre Zertifikate sind ungültig? Ich hatte in der Vergangenheit ein ähnliches Problem und die Umleitung von http zu https löste das Problem

montrealmike
quelle
0

Ich habe überprüft, ob <% = csrf_meta_tags%> vorhanden sind, und das Löschen von Cookies im Browser hat für mich funktioniert.

Praveen KJ
quelle
0

Nach den Empfehlungen von Chrome Lighthouse für ein schnelleres Laden der Anwendung habe ich mein Javascript asynchronisiert:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

Dies hat alles kaputt gemacht und den Token-Fehler für meine Remote-Formulare erhalten. Durch Entfernen wurde async: truedas Problem behoben.

Maxence
quelle
0

Diese Antwort ist viel spezifischer für Ruby on Rails, aber hoffentlich hilft sie jemandem.

Sie müssen das CSRF-Token in jede Nicht-GET-Anforderung aufnehmen. Wenn Sie an die Verwendung von JQuery gewöhnt sind, verfügt Rails über eine Hilfsbibliothek, die jquery-ujsdarauf aufbaut und einige versteckte Funktionen hinzufügt. Eines der Dinge, die es tut, ist automatisch das CSRF-Token in jede ajaxAnfrage aufzunehmen. Siehe hier .

Wenn Sie wie ich davon abweichen, haben Sie möglicherweise einen Fehler. Sie können das Token einfach manuell senden oder eine andere Bibliothek verwenden, um das Token aus dem DOM zu entfernen. Weitere Informationen finden Sie in diesem Beitrag .

user2490003
quelle
-1

In Schienen 5 müssen 2 Codezeilen hinzugefügt werden

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception
giapnh
quelle
-2

Installieren

gem 'remotipart' 

kann helfen

Alexei.B
quelle
3
Dies mag zwar die Antwort sein, aber es ist auch hilfreich, den wesentlichen Teil der Antwort aufzunehmen und zu erklären, warum / wie es funktioniert.
Roy Lee
-15

Problem durch Herabstufung von 2.3.8 auf 2.3.5 gelöst. (sowie das berüchtigte Problem "Sie werden umgeleitet.")

Nikita Rybak
quelle
@Flip Vielleicht ist es eine Idee, die akzeptierte Antwort zu aktualisieren?
Lafeber