LoginSignup
4
2

More than 3 years have passed since last update.

rails4 -> rails5 にアップデートしようとしたら、ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. のエラーが出るようになった

Posted at

何が起きたのか

rails4 -> 5 へのアップグレードガイドに、 rails5 からは protect_from_forgeryは今後デフォルトでprepend: falseに設定される と書かれているので、今までの挙動を変えたくないということで、

- protect_from_forgery
+ protect_from_forgery prepend: true, with: :exception`

に変更。 with: :exception オプションは prepend: true を設定したときに RuboCop だかに指摘されたので設定。

そうすると、 ajax で部分テンプレートを返す実装をしている ajax/hogehoge というエンドポイントで下記のエラーが発生しているよ、というエラー通知が飛んでくるようになった。

ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript

TL;DR

routes.rb 内のエラーが起きているエンドポイントを設定しているルーティングで constraints オプションを設定し、 XMLHttpRequest だけを受け付けるようにしてあげればいい。 ajax/hogehoge みたいなエンドポイントだったら下のような感じ。

namespace 'ajax' do
  get 'hogehoge', constraints: lambda { |req| req.xhr? }
end

問題の再現方法

エラーが起きていた、 ajax/hogehoge にブラウザから直接 ajax/hogehoge.js といった感じでアクセスしてあげると発生。

起こった問題の原因

  • ajax/hogehoge はとあるページからの ajax 通信でアクセスされることを想定したエンドポイントだった。
  • そのエンドポイントに対し、ブラウザから直接アクセスしたことにより発生。
  • rails5 移行の実装を入れる前は、 protect_from_forgery with: :exception のオプションが設定されていなかったため、エラーは起きているものの例外が投げられずスルーされていた。(ということは ここのコメントを見て予想)

対応方針

一番簡単なのは、 rails4 の時と同じ挙動になるように、

protect_from_forgery prepend: true, with: :null_session

に設定してあげる方法。(未検証ですが多分ちゃんと動く)
ただ、 rails5 の推奨は with: :exception らしいので、 このオプションを設定した上でどうにかしたい。

また、今回の問題は ajax 通信を期待しているエンドポイントに対して、非 ajax 通信が来たことにより発生しているので、コントローラレイヤとかではなくルーティングのレイヤでどうにかしたい。

対応内容

routes.rb 内のエラーが起きているエンドポイントを設定しているルーティングで constraints オプションを設定してあげる。 ajax/hogehoge みたいなエンドポイントだったら下のような感じ。

namespace 'ajax' do
  get 'hogehoge', constraints: lambda { |req| req.xhr? }
end

constraints オプションに関しては、 railsガイドに詳細が乗っているのでそちらを参考にしてください。

constraints オプションでは、 受け付けるリクエストに制限を課すことができるので、 lambda を用いて、リクエストが XMLHttpRequest (ajaxのリクエスト)であるかどうかを検証している感じです。

この設定により、 ajax/hogehoge に ajax でリクエストをする場合は、 Ajax#Hogehoge コントローラーが呼び出され正常にレスポンスが返されるが、 ブラウザから `ajax/hogehoge.js などでアクセスした場合は 404 エラーを返すようになる。

終わりに

rails6も出ていることですし、あんまり今回のような問題で詰まることもないかと思いますが、せっかくだったので記事にしてみました。個人的には、 rails のコードを読んだりするいい機会になったので結構楽しかったです。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2