Error "ActionController :: InvalidAuthenticityToken" saat menggunakan form_with

Sep 16 2020

Saya memiliki formulir yang terlihat seperti ini:

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

Segera setelah pengiriman formulir:

Catatan:

  • Ini terjadi di aplikasi (bukan API), jadi sesi itu penting, oleh karena itu perlindungan CSRF harus tetap aktif.
  • Masalahnya terjadi di chrome, incognito, dan safari.
  • Saya telah mencoba masuk dengan pengguna yang berbeda dan menghapus cookie (seandainya itu disebabkan oleh token basi )

Beberapa lagi pesan kesalahan:

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'

Memperbarui

Saya kembali ke versi kerja terakhir dari formulir, yang persis sama seperti di atas tetapi tanpa , local: true. Lalu tiba-tiba berhasil! (tidak ada kesalahan).

Saya pikir local: true(atau remote: false) hanya mematikan pengiriman formulir ajax. Jadi saya tidak mengerti mengapa hal itu akan membuat perbedaan (atau ada hubungannya dengan CSRF), sepertinya kedua aspek itu tidak terkait dan tidak jelas mengapa kedua konsep ini akan saling mempengaruhi satu sama lain.

Perbarui 2

Saya kemudian menyadari bahwa formulir kerja sebelumnya yang tidak tersentuh juga menghasilkan kesalahan ini. Itu tidak diubah dengan cara apapun. Saya mencobanya dalam penyamaran chrome, dan menghasilkan kesalahan. Setengah jam kemudian (tanpa mengubah kode apa pun) saya mencobanya lagi di browser yang sama dan berhasil. Perilaku (sangat) aneh ini membuat saya berpikir itu ada hubungannya dengan sesi, cookie, atau caching. Saya akan melaporkan kembali jika saya mempelajari lebih lanjut

Perbarui 3

Setelah membaca solusi Sarah yang ditambahkan protect_from_forgery prepend: trueke pengontrol aplikasi (saya mencoba sebelum dan sesudah before_action :authenticate_user!), pesan kesalahan yang sama muncul di log, permintaan POST tidak ditindaklanjuti, tetapi aplikasi mengalihkan ke halaman beranda. Yaitu setelah POST saya melihat:

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)

Perbarui 4

Saya mencoba untuk membersihkan cache fragmen rel secara manual (dengan Rails.cache.clear ). Tetapi hasilnya sama persis sebelum / sesudah mengosongkan cache fragmen.

Jawaban

2 SarahMarie Sep 17 2020 at 06:46

Saya ingat mengalami sesuatu seperti ini dan menambahkan protect_from_forgery prepend: truesebelum otentikasi pengguna apa pun untuk ApplicationControllermenyelesaikannya.

1 stevec Sep 17 2020 at 20:18

TL; DR: setelah 2 minggu upaya debugging, saya mematikan turbolinks dan masalahnya hilang .

Selain mematikan turbolink, solusi lain tampaknya (disebutkan di sini ) menambahkan ini keapplication.js

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

Jawaban sebelumnya

Masalah itu terus muncul kembali. Saya telah mencoba enam hal berikut tetapi masih belum memperbaikinya

1. Kosongkan cache fragmen

Rails.cache.clear( peringatan karena itu membersihkan cache, itu juga akan menghapus hal-hal seperti pekerjaan sidekiq dll). Ini akan menghapus token basi dan menyegarkan aplikasi di browser akan mengembalikan semuanya ke normal, dan formulir harus dikirim ('kirim ulang' sederhana tidak akan berfungsi, jadi kembali ke halaman formulir, segarkan, lalu kirim dan itu harus kerja)

2. Refresh halaman keras

Tekan cmd+ opt+ juntuk membuka konsol pengembang, lalu klik kanan pada refresh dan pilih 'Empty Cache and Hard Reload'

3. Hapus cookie situs

Klik kanan ikon kecil di sebelah kiri langsung url (ini akan menjadi kunci jika menggunakan https, atau huruf 'i' jika menggunakan http). Pergilah ke setiap kategori yang terdaftar (misalnya 'Cookies', 'Site Settings' dll) dan hapus semuanya

4. Hapus cookie untuk url lain yang mengarah ke situs yang sama

Misalnya, jika situs Anda adalah www.example.com, dan dihosting di heroku di www.example.herokuapp.com, maka hapus juga cookie untuk url kedua tersebut

5. Hapus cookie untuk localhost

Saya menghapus cookie localhost hanya untuk memastikan

6. Menguji dalam contoh chrome yang sepenuhnya terisolasi