Fehler "ActionController :: InvalidAuthenticityToken" bei Verwendung von form_with

Sep 16 2020

Ich habe ein Formular, das so aussieht:

  <%= form_with(url: star.starname, method: :post, local: true) do |f| %> 
    <% star.availabilities.each do |avail| %> 

    <%= f.label avail.time_slot %> 
      <%= radio_button_tag(:time_slot, avail.time_slot) %> <br>
    <% end %> 

  <%= f.submit "Create" %>
  <% end %> 

Unmittelbar nach dem Absenden des Formulars:

Anmerkungen:

  • Dies tritt in einer App (nicht in einer API) auf, daher sind Sitzungen wichtig, daher muss der CSRF-Schutz aktiviert bleiben.
  • Das Problem tritt bei Chrom, Inkognito und Safari auf.
  • Ich habe versucht, mich mit verschiedenen Benutzern anzumelden und Cookies zu löschen (falls dies durch ein veraltetes Token verursacht wurde ).

Noch etwas von der Fehlermeldung:

Started POST "/talljohn" for ::1 at 2020-09-16 10:06:21 +1000
Processing by StarsController#book as HTML
  Parameters: {"authenticity_token"=>"P++4a+giwUBqZgCLfMwqKpMu0EGitd8zTOi5RWsnxpKlNcjiuU6hd3ebbIC/IOxlL74RJIvrq+yDuA1ZtfcvFw==", "time_slot"=>"2020-09-16 01:00:00 UTC", "commit"=>"Create", "starname"=>"talljohn"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 655)


  
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
  
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:215:in `handle_unverified_request'
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:247:in `handle_unverified_request'
devise (4.7.2) lib/devise/controllers/helpers.rb:255:in `handle_unverified_request'
actionpack (6.0.3.2) lib/action_controller/metal/request_forgery_protection.rb:242:in `verify_authenticity_token'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:428:in `block in make_lambda'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:200:in `block (2 levels) in halting'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:201:in `block in halting'

Aktualisieren

Ich kehrte zur letzten Arbeitsversion des Formulars zurück, die genau die gleiche wie oben war, jedoch ohne , local: true. Dann klappt es plötzlich! (keine Fehler).

Ich dachte local: true(oder remote: false) schalte einfach die Ajax-Formularübermittlung aus. Ich verstehe also nicht, warum dies einen Unterschied machen würde (oder irgendetwas mit CSRF zu tun haben würde). Es scheint, dass diese beiden Aspekte nichts miteinander zu tun haben und es ist nicht klar, warum diese beiden Konzepte sich gegenseitig beeinflussen würden

Update 2

Später wurde mir klar, dass eine andere unberührte, zuvor funktionierende Form ebenfalls diesen Fehler verursachte. Es war in keiner Weise verändert worden. Ich habe es inkognito in Chrom versucht und es hat den Fehler erzeugt. Eine halbe Stunde später (ohne Code zu ändern) habe ich es im selben Browser erneut versucht und es hat funktioniert. Dieses (sehr) seltsame Verhalten lässt mich denken, dass es etwas mit Sitzungen, Cookies oder Caching zu tun hat. Ich melde mich zurück, wenn ich etwas weiter lerne

Update 3

Nach dem Lesen von Sarahs Lösung zum Hinzufügen protect_from_forgery prepend: truezum Anwendungscontroller (ich habe es sowohl vorher als auch nachher versucht before_action :authenticate_user!) wird dieselbe Fehlermeldung in den Protokollen angezeigt. Die POST-Anforderung wird nicht ausgeführt, aber die App leitet zur Startseite weiter. Dh nach POST sehe ich:

Can't verify CSRF token authenticity.
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms | Allocations: 444)


Started GET "/users/sign_in" for ::1 at 2020-09-17 21:08:42 +1000
Processing by Devise::SessionsController#new as HTML
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
Redirected to http://localhost:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 3ms (ActiveRecord: 0.5ms | Allocations: 1900)

Update 4

Ich habe versucht, den Rails-Fragment-Cache (mit Rails.cache.clear ) manuell zu löschen . Das Ergebnis ist jedoch genau das gleiche vor / nach dem Löschen des Fragment-Cache.

Antworten

2 SarahMarie Sep 17 2020 at 06:46

Ich erinnere mich, dass ich auf so etwas gestoßen bin und protect_from_forgery prepend: truevor jeder Benutzerauthentifizierung das ApplicationControllerProblem gelöst habe.

1 stevec Sep 17 2020 at 20:18

TL; DR: Nach zweiwöchigen Debugging-Versuchen habe ich Turbolinks ausgeschaltet und das Problem ist behoben .

Abgesehen vom Ausschalten der Turbolinks scheint eine andere Lösung ( hier erwähnt ) darin zu bestehen, diese zu ergänzenapplication.js

$(document).on('turbolinks:load', function(){ $.rails.refreshCSRFTokens(); });

Vorherige Antwort

Das Problem tauchte immer wieder auf. Ich habe die folgenden sechs Dinge ausprobiert, aber es wurde immer noch nicht behoben

1. Leeren Sie den Fragment-Cache

Rails.cache.clear( Warnung, da der Cache geleert wird, werden auch Sidekiq-Jobs usw. entfernt). Dadurch wird das veraltete Token entfernt und durch das Aktualisieren der App im Browser wird der Normalzustand wiederhergestellt, und das Formular sollte gesendet werden (ein einfaches erneutes Senden funktioniert nicht. Gehen Sie also zur Formularseite zurück, aktualisieren Sie es und senden Sie es Arbeit)

2. Harte Aktualisierungsseite

Drücken Sie cmd+ opt+ j, um die Entwicklerkonsole aufzurufen. Klicken Sie dann mit der rechten Maustaste auf Aktualisieren und wählen Sie "Cache leeren und neu laden".

3. Löschen Sie Site-Cookies

Klicken Sie mit der rechten Maustaste auf das winzige Symbol unmittelbar links neben der URL (es ist eine Sperre, wenn Sie https verwenden, oder der Buchstabe 'i', wenn Sie http verwenden). Gehen Sie in jede der aufgelisteten Kategorien (z. B. "Cookies", "Site-Einstellungen" usw.) und löschen Sie alle

4. Löschen Sie Cookies für andere URLs, die auf dieselbe Site verweisen

Wenn Ihre Website beispielsweise www.example.comauf heroku unter gehostet wird www.example.herokuapp.com, löschen Sie auch Cookies für diese zweite URL

5. Löschen Sie Cookies für localhost

Ich habe localhost-Cookies gelöscht, nur um sicherzugehen

6. Testen in vollständig isolierten Chromfällen