1. ホーム
  2. ruby-on-rails

[解決済み] Rails CSRF Protection + Angular.js: protect_from_forgery で POST でログアウトする。

2022-07-07 14:01:18

質問

もし protect_from_forgery オプションがapplication_controllerに記述されている場合、ログインして任意のGETリクエストを実行できますが、最初のPOSTリクエストでRailsはセッションをリセットし、私をログアウトさせるのです。

私は protect_from_forgery オプションを一時的にオフにしましたが、Angular.jsで使用したいと思います。何か方法があるのでしょうか?

どのように解決するのですか?

DOMからCSRF-valueを読み取るのは良い解決策ではなく、あくまで回避策だと思います。

angularJSの公式サイトにこんな文書がありました。 http://docs.angularjs.org/api/ng.$http :

あなたのドメインで動作するJavaScriptだけがクッキーを読むことができるので、あなたのサーバーはXHRがあなたのドメインで動作するJavaScriptから来たものであることを保証することができるのです。

この機能(CSRF保護)を利用するために、サーバーはJavaScriptが読み取り可能なセッション XSRF-TOKENと呼ばれるクッキーにトークンを設定する必要があります。その後の GET 以降のリクエストでは、サーバーはそのクッキーが X-XSRF-TOKEN HTTPヘッダー

以下は、これらの指示に基づく私の解決策です。

まず、Cookieを設定します。

# app/controllers/application_controller.rb

# Turn on request forgery protection
protect_from_forgery

after_action :set_csrf_cookie

def set_csrf_cookie
  cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end

次に、GET以外のリクエストのたびにトークンを検証する必要があります。

Railsにはすでに同様のメソッドが構築されているので、それをオーバーライドしてロジックを追加すればよいのです。

# app/controllers/application_controller.rb

protected
  
  # In Rails 4.2 and above
  def verified_request?
    super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
  end

  # In Rails 4.1 and below
  def verified_request?
    super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
  end