Wenn die protect_from_forgery
Option in application_controller erwähnt wird, kann ich mich anmelden und alle GET-Anforderungen ausführen. Bei der ersten POST-Anforderung setzt Rails jedoch die Sitzung zurück, wodurch ich abgemeldet werde.
Ich habe die protect_from_forgery
Option vorübergehend deaktiviert, möchte sie aber mit Angular.js verwenden. Gibt es eine Möglichkeit, das zu tun?
Antworten:
Ich denke, das Lesen des CSRF-Werts aus DOM ist keine gute Lösung, sondern nur eine Problemumgehung.
Hier ist ein Dokument auf der offiziellen Website von angleJS http://docs.angularjs.org/api/ng.$http :
Hier ist meine Lösung basierend auf diesen Anweisungen:
Setzen Sie zuerst den Cookie:
Dann sollten wir das Token bei jeder Nicht-GET-Anforderung überprüfen.
Da Rails bereits mit der ähnlichen Methode erstellt hat, können wir sie einfach überschreiben, um unsere Logik anzuhängen:
quelle
Wenn Sie den Standard-Rails-CSRF-Schutz (
<%= csrf_meta_tags %>
) verwenden, können Sie Ihr Angular-Modul folgendermaßen konfigurieren:Oder wenn Sie kein CoffeeScript verwenden (was!?):
Wenn Sie möchten, können Sie den Header nur bei Nicht-GET-Anforderungen mit den folgenden Angaben senden:
Lesen Sie auch unbedingt die Antwort von HungYuHei , die alle Grundlagen auf dem Server und nicht auf dem Client abdeckt.
quelle
<%= csrf_meta_tags %>
. Ich dachte, dass es genug geben sollte, um nur zu erwähnenprotect_from_forgery
. Was ist zu tun? Das Basisdokument muss ein einfaches HTML sein (ich bin hier nicht derjenige, der wählt).protect_from_forgery
was Sie sagen, ist "Wenn mein JavaScript-Code Ajax-Anfragen stellt, verspreche ich, eineX-CSRF-Token
im Header zu senden , die dem aktuellen CSRF-Token entspricht." Um dieses Token zu erhalten, fügt Rails es<%= csrf_meta_token %>
mit jQuery in das DOM ein und ruft den Inhalt des Meta-Tags ab, wenn Ajax-Anforderungen gestellt werden (der Standard-Rails 3-UJS-Treiber erledigt dies für Sie). Wenn Sie ERB nicht verwenden, gibt es keine Möglichkeit, das aktuelle Token von Rails in die Seite und / oder das JavaScript zu übertragen. Daher können Sie es nichtprotect_from_forgery
auf diese Weise verwenden.csrf_meta_tags
jedes Mal empfängt, wenn der Server eine Antwort generiert, und jedes Mal, wenn sich diese Tags von den vorherigen unterscheiden. Diese Tags sind also für jede Anforderung eindeutig. Die Frage ist: Wie empfängt die Anwendung diese Tags für eine AJAX-Anfrage (ohne Winkel)? Ich habe protected_from_forgery mit jQuery-POST-Anforderungen verwendet, mich nie darum gekümmert, dieses CSRF-Token zu erhalten, und es hat funktioniert. Wie?jQuery.ajaxPrefilter
wie hier gezeigt verwendet: github.com/indirect/jquery-rails/blob/c1eb6ae/vendor/assets/… Sie können diese Datei lesen und alle Rahmen anzeigen, durch die Rails springt, damit sie praktisch funktioniert, ohne dass dies erforderlich ist Sorgen Sie sich darum.put
undpost
statt an zu tuncommon
? Aus dem Rails Security Guide :The solution to this is including a security token in non-GET requests
Das Juwel angular_rails_csrf fügt allen Ihren Controllern automatisch Unterstützung für das in der Antwort von HungYuHei beschriebene Muster hinzu :
quelle
angular_rails_csrf
funktioniert das Juwel nicht mit Rails 5. Das Konfigurieren von Angular-Anforderungsheadern mit dem Wert aus dem CSRF-Meta-Tag funktioniert jedoch!Die Antwort, die alle vorherigen Antworten zusammenführt und davon abhängt, dass Sie das
Devise
Authentifizierungsjuwel verwenden.Fügen Sie zunächst den Edelstein hinzu:
Fügen Sie als Nächstes einen
rescue_from
Block in application_controller.rb hinzu:Und zum Schluss fügen Sie das Interceptor-Modul zu Ihrer Winkel-App hinzu.
quelle
$injector
anstatt nur direkt zu injizieren$http
?Ich sah die anderen Antworten und fand sie großartig und gut durchdacht. Ich habe meine Rails-App mit einer meiner Meinung nach einfacheren Lösung zum Laufen gebracht, also dachte ich, ich würde sie teilen. Meine Rails-App wurde mit dieser Standardeinstellung geliefert.
Ich habe die Kommentare gelesen und es schien so, als ob ich Angular verwenden und den CSRF-Fehler vermeiden möchte. Ich habe es geändert,
Und jetzt funktioniert es! Ich sehe keinen Grund, warum dies nicht funktionieren sollte, aber ich würde gerne Einblicke von anderen Postern erhalten.
quelle
Ich habe den Inhalt der Antwort von HungYuHei in meiner Bewerbung verwendet. Ich stellte jedoch fest, dass ich einige zusätzliche Probleme hatte, einige aufgrund der Verwendung von Devise zur Authentifizierung und einige aufgrund der Standardeinstellungen, die ich mit meiner Anwendung erhalten habe:
Ich notiere die zugehörige Frage zum Stapelüberlauf und die Antworten dort und habe einen viel ausführlicheren Blog-Beitrag geschrieben , in dem die verschiedenen Überlegungen zusammengefasst sind. Die Teile dieser Lösung, die hier relevant sind, sind im Anwendungscontroller:
quelle
Ich habe einen sehr schnellen Hack dazu gefunden. Ich musste nur Folgendes tun:
ein. Meiner Ansicht nach initialisiere ich eine
$scope
Variable, die das Token enthält, beispielsweise vor dem Formular, oder noch besser bei der Controller-Initialisierung:b. In meinem AngularJS-Controller füge ich vor dem Speichern meines neuen Eintrags das Token dem Hash hinzu:
Es muss nichts mehr getan werden.
quelle
Es funktioniert auf eckiger Seite!
quelle