InvalidAuthenticityTokenから学ぶ エラー解決の考え方【Rails】
移転しました。3秒後に移転先へ移動します。
Railsでテキスト入力やチェックボックスやラジオボタンなど、フォームのページを作って送信ボタンを押したときに出たエラー。Authenticity Tokenとな…?
プログラミング初心者ゆえに知識や経験がほぼなくても、こんなふうに考え方を工夫すれば解決できた^^というエラー備忘録です。
- エラー内容:Invalid Authenticity Token
- エラー文の理解(Railsもプログラミングも初心者がシンプルに考えてみる)
- 推察してからコードを見なおす => 発見・修正・解決!
- まとめ
エラー内容:Invalid Authenticity Token
エラー画面↓ testコントローラのshowアクションでエラーね。ハイ
↓ 入力フォームのHTMLファイル。右はそのフォームのブラウザ表示。
↓ testコントローラのshowアクション部分。
今回はモデル移行前で、まずコントローラに処理を書いています。
で。送信するとエラーになると。。
コード文眺めてるとなんとなく見当がつきそうではありますが、根拠となりそうなページ を探すことで初心者なりに、おおよそでも納得できるところまで理解を持っていこうと思いました。
エラー文の理解(Railsもプログラミングも初心者がシンプルに考えてみる)
invalid :無効な
authentic :本物の
authenticity(名) :真偽性、信頼性
token :記号・象徴
Authenticity TokenでググってみるとCSRF(しーさーふ)対策というワードに行き当たります。
verify_authenticity_token メソッド
大雑把に説明すると、verify_authenticity_token メソッドはHTTPリクエストのヘッダーやボディに入っているCSRF対策用トークンの値を検証するメソッドです。検証した結果、不正だと判断した場合に InvalidAuthenticityToken エラーを発生します。(このエラーは protect_from_forgery メソッドのwithオプションに :exception を渡したときに発生します。
(中略)
このメソッドでは以下の5つの項目を検証していきます。
- 設定ファイルで config.application_controller.allow_forgery_protection を false に設定しているか
- リクエストのHTTPメソッドがGETであるか
- リクエストのHTTPメソッドがHEADであるか
- セッション変数 _csrf_token の値とリクエストボディの authenticity_token の値を比較した結果、正しいと判断されるか
- セッション変数 _csrf_token の値とリクエストヘッダーの X-CSRF-Token の値を比較した結果、正しいと判断されるか
引用元:
あとこちらも
Rails では、デフォルトで CSRF の対応がされています。
これは、セッション内に _csrf_token というキーで保存された値と、 POST 時に hidden field の authenticity_token で指定された値を比較することで、実現されています。
Ajax の場合には HTTP ヘッダ内に指定することもありますが、あまり関係ないので省略します。要は、 CSRF トークンという、セッション毎にランダムに生成される値が、 POST で渡されてくる値と一致しているかを見ています。
引用元:
ふむ…つまりものすごくシンプルに考えると…
postで送信されたときに値がおかしいっていうエラーのようだぞ!
(送信ボタン押してエラーが発生したことからも間違いないと見える)
推察してからコードを見なおす => 発見・修正・解決!
ということで先ほどのコードの見なおしをしたところ、ありましたー!!
HTMLテキスト入力フォームの性別欄と、
同じファイルの下の方で性別ラジオボタンを作ってるところ、同じgenderをキーにしていました。
そしてコントローラ側でも(笑)
修正。
被っているとこ、どっちかのを消せばよいので、テキスト入力フォームの方の性別欄をなくしました。HTMLファイル・コントーラの処理のとこでgenderを含む記述をコメントアウト。
これでgenderをキーにして値を送ってるのはラジオボタンフォームだけになりました。
改めて送信ボタンをポチ!
↓
うむ!できた!!^^
-------------------------------------------------------------------------------------------------------------------
※このエラー文についてもう少し説明:
変な値が登録されないようにデータベース側では、不正な値があった場合はそれを弾いてくれている(invalid)。
今回のように同じキーなのに別々の値を送信してたため、どれを登録していいか?どれを信じていいのか?(真偽性、信頼性が疑われる = authenticity)
とエラーを出しているようです。
まとめ
漫然とコードを眺めててもなんとなく予想がつくエラーですが、こうやって根拠となる記述を探した上で、改めて自分で考えてみることで今後のエラー対処の糧になりそう。
考え方や着目するところ、などのコツを会得できれば広く応用が利かせられて大きな武器になると思います。思考ルートを切り開くって大事だなー
ここまで読んでくださり、ありがとうございました^^