#開発環境
- OS:macOS Big Sur 11.2.2
- Ruby:2.6.5
- Ruby on Rails:6.0.0
- テキストエディタ:Visual Studio Code
#課題
twitterのいいねボタンを押下したときのように、非同期通信でDB更新しつつWebページの見た目を変えたかった。
今回はXHRオブジェクトを作って実装。
~
XHR.open('POST', URL, true);
XHR.send();
このリクエストが422エラーになる。もう少し詳細を追ってみると、
「ActionController::InvalidAuthenticityToken」
というエラーだった。
CSRFとrailsのCSRF対策について
CSRF=クロスサイトリクエストフォージェリとは脆弱性のあるWebアプリケーションに対し悪意のあるリクエストを送り攻撃すること。
railsではCSRF対策メソッドとしてprotect_from_forgeryが用意されている。
こちらrails5.2より前のverでは、アプリケーション生成した際に自動でapplication_controller.rb
に記述されていたらしく、簡単に言うとリクエストに含まれたトークンを精査することで悪意のあるリクエストでないかチェックするというもの。(5.2以降のverでは継承元のActionController::Base
に記載されている。)
link_toやform_withなどのヘルパーメソッドを使った場合、またjQueryを使ったリクエストはこの認証に使うトークンを自動生成して付与してくれるらしいが、JavaScriptのみでリクエストを生成して送信した場合はこのトークンがないのでチェックに引っ掛かってしまう。今回のエラーはそれが原因。
#解決方法
検証そのものを完全無効化するやり方もあるらしいが、それは怖いので
class ClipsController < ApplicationController
skip_forgery_protection
end
この一文を対象のコントローラーの最初に記載した。
skip_forgery_protection
は名前の通り、トークン検証をここではskipしますというメソッド。これでエラー解消できた。