Lỗi “ActionController :: InvalidAuthenticityToken” khi sử dụng form_with

Sep 16 2020

Tôi có một biểu mẫu giống như sau:

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

Ngay sau khi gửi biểu mẫu:

Ghi chú:

  • Điều này xảy ra trong một ứng dụng (không phải API), do đó, các phiên là quan trọng, do đó, bảo vệ CSRF phải được bật.
  • Sự cố xảy ra trong chrome, ẩn danh và safari.
  • Tôi đã thử đăng nhập với những người dùng khác nhau và xóa cookie (trong trường hợp nó được gây ra bởi mã thông báo cũ )

Một số thông báo lỗi khác:

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'

Cập nhật

Tôi đã hoàn nguyên về phiên bản làm việc cuối cùng của biểu mẫu, phiên bản này giống hệt như trên nhưng không có , local: true. Sau đó, nó đột nhiên hoạt động! (không có lỗi).

Tôi nghĩ local: true(hoặc remote: false) chỉ đơn giản là tắt gửi biểu mẫu ajax. Vì vậy, tôi không hiểu tại sao điều đó lại tạo ra bất kỳ sự khác biệt nào (hoặc có liên quan gì đến CSRF), có vẻ như hai khía cạnh đó không liên quan và không rõ tại sao hai khái niệm này lại có bất kỳ ảnh hưởng nào đến nhau.

Cập nhật 2

Sau đó tôi nhận ra rằng một biểu mẫu làm việc chưa được chạm khác trước đó cũng tạo ra lỗi này. Nó đã không được thay đổi theo bất kỳ cách nào. Tôi đã thử nó ở chế độ ẩn danh chrome và nó tạo ra lỗi. Nửa giờ sau (không thay đổi bất kỳ mã nào) tôi đã thử lại trong cùng một trình duyệt và nó hoạt động. Hành vi (rất) kỳ lạ này khiến tôi nghĩ rằng đó là điều gì đó liên quan đến phiên, cookie hoặc bộ nhớ đệm. Tôi sẽ báo cáo lại nếu tôi biết thêm bất cứ điều gì

Cập nhật 3

Sau khi đọc giải pháp của Sarah thêm protect_from_forgery prepend: truevào bộ điều khiển ứng dụng (tôi đã thử cả trước và sau before_action :authenticate_user!), thông báo lỗi tương tự xuất hiện trong nhật ký, yêu cầu ĐĂNG không được kích hoạt nhưng ứng dụng chuyển hướng đến trang chủ. Tức là khi ĐĂNG tôi thấy:

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)

Cập nhật 4

Tôi đã cố gắng xóa thủ công bộ nhớ cache phân đoạn đường ray (với Rails.cache.clear ). Nhưng kết quả hoàn toàn giống nhau trước / sau khi xóa bộ đệm phân mảnh.

Trả lời

2 SarahMarie Sep 17 2020 at 06:46

Tôi nhớ đã chạy vào một cái gì đó như thế này và thêm protect_from_forgery prepend: truetrước khi bất kỳ xác thực người dùng nào để ApplicationControllergiải quyết nó.

1 stevec Sep 17 2020 at 20:18

TL; DR: sau 2 tuần cố gắng gỡ lỗi, tôi đã tắt turbolinks và sự cố đã biến mất .

Ngoài việc tắt turbolinks, một giải pháp khác dường như (được đề cập ở đây ) thêm điều này vàoapplication.js

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

Câu trả lời trước

Vấn đề vẫn tiếp tục tái diễn. Tôi đã thử sáu cách sau đây nhưng vẫn không khắc phục được

1. Xóa bộ đệm phân mảnh

Rails.cache.clear( cảnh báo vì nó xóa bộ nhớ cache, nó cũng sẽ xóa những thứ như sidekiq job, v.v.). Thao tác này sẽ xóa mã thông báo cũ và việc làm mới ứng dụng trong trình duyệt sẽ đưa mọi thứ trở lại bình thường và biểu mẫu sẽ được gửi ('gửi lại' đơn giản sẽ không hoạt động, vì vậy hãy quay lại trang biểu mẫu, làm mới, sau đó gửi và nó sẽ công việc)

2. Làm mới trang cứng

Nhấn cmd+ opt+ jđể hiển thị bảng điều khiển dành cho nhà phát triển, sau đó nhấp chuột phải vào làm mới và chọn 'Empty Cache and Hard Tải lại'

3. Xóa cookie trang web

Nhấp chuột phải vào biểu tượng nhỏ ở ngay bên trái của url (nó sẽ là một ổ khóa nếu sử dụng https hoặc chữ 'i' nếu sử dụng http). Đi vào từng danh mục được liệt kê (ví dụ: 'Cookie', 'Cài đặt trang web', v.v.) và xóa tất cả chúng

4. Xóa cookie cho các url khác trỏ đến cùng một trang web

Ví dụ: nếu trang web của bạn có www.example.comvà được lưu trữ trên heroku tại www.example.herokuapp.com, thì hãy xóa cookie cho url thứ hai đó

5. Xóa cookie cho localhost

Tôi đã xóa cookie localhost chỉ để chắc chắn

6. Thử nghiệm trong các trường hợp hoàn toàn bị cô lập của chrome