form_with 사용시 "ActionController :: InvalidAuthenticityToken"오류
다음과 같은 양식이 있습니다.
<%= 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 %>
양식 제출 직후 :
메모:
- 이는 API가 아닌 앱에서 발생하므로 세션이 중요하므로 CSRF 보호가 켜져 있어야합니다.
- 크롬, 시크릿 및 사파리에서 문제가 발생합니다.
- 다른 사용자로 로그인하고 쿠키를 지우려고 시도했습니다 ( 부실 토큰 으로 인해 발생한 경우 ).
더 많은 오류 메시지 :
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'
최신 정보
위와 똑같지 만 .NET이없는 양식의 마지막 작업 버전으로 되돌 렸습니다 , local: true. 그러면 갑자기 작동합니다! (오류 없음).
나는 local: true(또는 remote: false) 단순히 ajax 양식 제출을 해제 한다고 생각 했습니다. 그래서 나는 그것이 왜 어떤 차이를 만드는지 이해하지 못합니다 (또는 CSRF와 관련이 있음), 그 두 측면이 관련이없는 것처럼 보이며이 두 개념이 왜 서로에게 영향을 미치는지 분명하지 않습니다
업데이트 2
나는 나중에 이전에 작업하지 않은 다른 양식에서도이 오류가 발생한다는 것을 깨달았습니다. 어떤 식 으로든 변경되지 않았습니다. 크롬 시크릿에서 시도했는데 오류가 발생했습니다. 30 분 후 (코드를 변경하지 않고) 동일한 브라우저에서 다시 시도했는데 작동했습니다. 이 (매우) 이상한 행동으로 인해 세션, 쿠키 또는 캐싱과 관련이 있다고 생각합니다. 더 배우면 다시보고하겠습니다
업데이트 3
Sarah의 솔루션protect_from_forgery prepend: true 을 애플리케이션 컨트롤러에 추가 한 후 (전과 후 모두 시도 before_action :authenticate_user!) 동일한 오류 메시지가 로그에 나타나고 POST 요청이 실행되지 않지만 앱이 홈 페이지로 리디렉션됩니다. 즉 POST에서 다음을 참조하십시오.
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)
업데이트 4
레일 조각 캐시를 수동으로 지우려고했습니다 Rails.cache.clear . 그러나 결과는 조각 캐시를 지우기 전후에 정확히 동일합니다.
답변
나는 이와 같은 것을 실행 protect_from_forgery prepend: true하고 ApplicationController해결 하기 전에 사용자 인증을 추가하는 것을 기억 합니다.
요약 : 2 주 동안 디버깅을 시도한 후 터보 링크를 끄고 문제가 해결되었습니다 .
이외에도 turbolinks 꺼지지, 또 다른 해결책은 (언급 한 것으로 보인다 여기 에이 추가)application.js
$(document).on('turbolinks:load', function(){ $.rails.refreshCSRFTokens(); });
이전 답변
문제는 계속해서 다시 나타났습니다. 다음 여섯 가지를 시도했지만 여전히 해결되지 않았습니다.
1. 조각 캐시 지우기
Rails.cache.clear( 캐시를 지우므로 경고 , sidekiq 작업 등과 같은 항목도 제거됩니다). 이렇게하면 오래된 토큰이 제거되고 브라우저에서 앱을 새로 고치면 모든 것이 정상으로 돌아가고 양식이 제출되어야합니다 (간단한 '다시 제출'이 작동하지 않으므로 양식 페이지로 돌아가서 새로 고침 한 다음 제출하면됩니다. 작업)
2. 하드 새로 고침 페이지
cmd+ opt+ j를 눌러 개발자 콘솔을 불러 온 다음 새로 고침을 마우스 오른쪽 버튼으로 클릭하고 '캐시 비우기 및 하드 새로 고침'을 선택합니다.
3. 사이트 쿠키 삭제
URL 바로 왼쪽에있는 작은 아이콘을 마우스 오른쪽 버튼으로 클릭 합니다 (https를 사용하는 경우 잠금, http를 사용하는 경우 'i'문자). 나열된 각 카테고리 (예 : '쿠키', '사이트 설정'등)로 이동하여 모두 삭제합니다.
4. 동일한 사이트를 가리키는 다른 URL에 대한 쿠키 삭제
예를 들어 사이트가 www.example.com이고 heroku에 호스팅 된 경우 www.example.herokuapp.com두 번째 URL에 대한 쿠키도 삭제합니다.
5. localhost에 대한 쿠키 삭제
확인하기 위해 로컬 호스트 쿠키를 삭제했습니다.
6. 완전히 격리 된 크롬 인스턴스 에서 테스트