web-dev-qa-db-ja.com

RailsでデフォルトでCookieを安全(httpsのみ)にするにはどうすればよいですか?

Railsコントローラでは、次のようにCookieを設定できます:

cookies[:foo] = "bar"

そして、「セキュア」(httpsのみ)フラグが次のようにオンになるように指定します。

cookies[:foo, :secure => true] = "bar"

:secureはデフォルトでfalseです。デフォルトで、アプリケーション全体でCookieを安全にするにはどうすればよいですか?

これはRails 2.3.8です。

33
John Bachir

@knxに感謝します、あなたは私を正しい道に送りました。これが私が思いついたモンキーパッチで、機能しているようです。

class ActionController::Response
  def set_cookie_with_security(key, value)
    value = { :value => value } if Hash != value.class
    value[:secure] = true
    set_cookie_without_security(key, value)
  end
  alias_method_chain :set_cookie, :security
end

どう思いますか?

4
John Bachir

ActionController/ActionDispatchにモンキーパッチを適用する必要はなく、force_sslには副作用があります(例: ELBの背後 )。

安全なCookieを実現する最も簡単な方法は、config/initializers/session_store.rbを変更することです。

MyApp::Application.config.session_store :cookie_store, key: '_my_app_session',
                                                       secure: Rails.env.production?
38
David Cain

Rails 3.1、 the Rails security guide によると、次のようにapplication.rb

config.force_ssl = true

これにより、Cookieはhttps経由でのみ送信されます(他のすべても想定しています)。

16
Markus
# session only available over HTTPS
ActionController::Base.session_options[:secure] = true
1
alsotang

SSLを強制し、Ruby on Railsアプリケーション全体でセキュアCookieを有効にするには、production.rbなどの環境ファイルでforce_sslを有効にします。

# config/environments/production.rb
config.force_ssl = true

Ruby on RailsアプリケーションでHTTPおよびHTTPSトラフィックをサポートする必要がある場合は、セッションCookieのみが送信されるように、アプリケーションのセキュアCookieフラグを設定しますHTTPS。

その結果、HTTP経由でセッション状態を維持できなくなりますが、少なくともセッションハイジャック攻撃から身を守ることができます。

# config/initializers/session_store.rb
# set secure: true, optionally only do this for certain Rails environments (e.g., Staging / Production
Rails.application.config.session_store :cookie_store, key: '_testapp_session', secure: true

ここ は同じのビデオチュートリアルです。

1
Imran

迅速かつ汚い解決策:アクションパックCookieモジュール(actionpack/lib/action_controller/cookies.rb)の[] =メソッドを変更することで可能だと思います

から:

    def []=(name, options)
      if options.is_a?(Hash)
        options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
        options["name"] = name.to_s
      else
        options = { "name" => name.to_s, "value" => options }
      end

      set_cookie(options)
    end

に:

    def []=(name, options)
      if options.is_a?(Hash)
        options.merge!({:secure => true})
        options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
        options["name"] = name.to_s
      else
        options = { "name" => name.to_s, "value" => options }
      end

      set_cookie(options)
    end
1
knx

Rack-ssl-enforcer gemを確認する必要があります。私はこれに対する明確な答えを探していましたが、どのバージョンのRailsを使用しているかに関係なく、問題を解決し、さらに非常に構成可能です。

0
brightball