ssl_requirement を改造して、https => http の画面遷移でブラウザの警告をなくす


Rails 作者の David Heinemeier Hansson 謹製プラグイン ssl_requirement は実によくできている。わずか40行のコード。だが、http と https の切り替えを完璧にやってくれる。

ruby script/plugin install http://dev.rubyonrails.org/svn/rails/plugins/ssl_requirement/

でインストールできる。


しかしながら巷では、こんなことが話題になっているらしい。

HTTPSの認証ページから認証後、HTTPのページへセキュリティーの警告無しにリダイレクトする方法

私にとっては正直、どうでもいいことだが、人によっては、あの警告に恐怖を感じるのかもしれない。われらが ssl_requirement は正しい作法に従って、302 Redirect で https => http の画面遷移を行う。したがって、セキュリティー警告が出るはずである。(出るはず、というのは、私のところでなぜか警告が出てくれないのだ。WEBrick on SSL を使っているせいか?)上記のサイトによれば、Javascript で location.href に遷移先 URL を指定してリダイレクトすれば、例の警告を回避できるという。

そこで、ssl_requirement を使って、なおかつ、セキュリティ警告を回避する方法を考えてみた。RAILS_ROOT/controllers/application.rb に下記のようなコードを追加する。

# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
  # Pick a unique cookie name to distinguish our session data from others'
  session :session_key => '_ssl_test_session_id'
  
  include SslRequirement
end

module SslRequirement
  def ensure_proper_protocol
    return true if ssl_allowed?

    if ssl_required? && !request.ssl?
      redirect_with_javascript(:https, request)
      return false
    elsif request.ssl? && !ssl_required?
      redirect_with_javascript(:http, request)
      return false
    end
  end
  
  def redirect_with_javascript(protocol, request)
    url = "#{protocol.to_s}://#{request.host}#{request.request_uri}"
    render :text => <<-EOS
<html>
<head>
<meta http-equiv="refresh" content="0; url=#{url}"> 
<script type="text/javascript">
location.href = "#{url}";
</script>
</head>
<body />
</html>
    EOS
  end
end

プラグイン自体たった40行なので、よく使うようなら、プラグイン自体を改造してしまったほうがいいかもしれない。RAILS_ROOT/vendor/plugin/ssl_requirement/lib/ssl_requirement.rb を開いて、ensure_proper_protocol を置き換え、redirect_to_url を追加すれば OK。こういう場合ってどうしたらいいんだろうな?プラグインの動き修正するプラグインというのはロードの順番の関係上、難しいかも。いずれにしろ、今回は DHH 様の美しいコードを汚す気になれなかったので、上のようなソリューションを提案した。まあ適当にやってください。