Как я могу сделать файлы cookie безопасными (только https) по умолчанию в rails?

В контроллере Rails я могу установить такой файл cookie:

cookies[:foo] = "bar"

И укажите, что флаг «безопасный» (только https) должен быть включен следующим образом:

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

:secure по умолчанию является ложным. Как обеспечить безопасность файлов cookie по умолчанию для всего приложения?

Это на Rails 2.3.8


person John Bachir    schedule 22.09.2010    source источник


Ответы (8)


Нет необходимости исправлять 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?
)
person David Cain    schedule 06.07.2015
comment
Это правильный ответ (проверено, что это работает в Rails 4.2.7.1). Чтобы легко проверить это, установите secure: true, и тогда вы сможете убедиться, что файл cookie сгенерирован правильно. Затем вы можете изменить его обратно на Rails.env.production? - person Debajit; 03.12.2016
comment
похоже, это повлияет только на файл cookie сеанса. Спрашивающее лицо запросил безопасный в качестве значения по умолчанию для всех файлов cookie. Может ли @david-cain проверить, работает ли это решение для всех файлов cookie? - person Mike P.; 15.09.2017

начиная с rails 3.1, согласно руководству по безопасности rails, вы можете просто установить следующее в вашем application.rb:

config.force_ssl = true

это заставляет cookie отправляться только через https (и я предполагаю, что все остальное тоже).

person Markus    schedule 21.09.2013
comment
Сначала это меня смутило: основная цель config.force_ssl — разрешить приложению rails работать только через SSL, но оно также включает флаг secure для файлов cookie. Прежде чем установить эту конфигурацию, убедитесь, что у вас все в порядке с остальными ее эффектами: stackoverflow.com/questions/15676596/ - person Shelvacu; 23.12.2020

Спасибо @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

Как вы думаете?

person John Bachir    schedule 23.09.2010
comment
Джон, где в приложении Rails мы поместим класс выше? - person Rafael; 18.05.2012
comment
отличный. Спасибо. еще одна вещь, я использую среду разработки - используя webrick - когда я устанавливаю флаг безопасности в true в environment.rb, я не могу пройти через экран входа в систему - я заметил, что в ответах есть файл cookie из приложения. Любая идея, что может быть один? - person Rafael; 18.05.2012
comment
если вы установите для своего файла cookie флаг безопасности в значение true, то файл cookie не будет отправляться для запросов, отличных от https. вы используете https в своей среде разработки? - person John Bachir; 19.05.2012
comment
я установил для своего файла cookie флаг безопасности в значение true (через ActionController::Base.session). я настроил apache httpd с ssl, который перенаправляется на WebRick в моей среде разработки и все равно ведет себя так же - person Rafael; 21.05.2012
comment
Для тех, кто пробует это на Rails 3.2.x, я считаю, что set_cookie был реорганизован в ActionDispatch::Response, поэтому вместо этого должно работать обезьянье исправление этого класса. - person Chris Hart; 04.11.2012

Чтобы принудительно использовать SSL и включить безопасный файл cookie для всего приложения Ruby on Rails, включите force_ssl в файле среды, таком как production.rb.

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

Если вам необходимо поддерживать HTTP- и HTTPS-трафик с вашим приложением Ruby on Rails, установите для своего приложения флаг безопасных файлов 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

Вот видеоурок того же самого.

person Imran Ahmad    schedule 02.01.2019

Быстрое и грязное решение: я думаю, это возможно, изменив метод []= в модуле файлов 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

to:

    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
person knx    schedule 23.09.2010

Вы должны посмотреть на гем Rack-ssl-enforcer. Я просто искал четкий ответ на этот вопрос, и он решает проблему независимо от того, на какой версии Rails вы работаете, плюс он чрезвычайно настраиваемый.

person brightball    schedule 17.06.2016
comment
Или камень secure_cookies. - person Franklin Yu; 01.05.2018

Вы можете сделать это, как указано в некоторых из приведенных выше ответов (используйте параметр secure в файле config/initializers/session_store.rb):

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

который защитит только файл cookie сеанса, но другие файлы cookie не будут защищены.

Если вы хотите защитить все файлы cookie в своем приложении Rails по умолчанию, вы можете использовать гем secure_headers. Просто добавьте гем secure_headers в свой Gemfile, гем bundle install и создайте файл config/initializers/secure_headers.rb со следующим содержимым:

SecureHeaders::Configuration.default do |config|
  config.cookies = {
    secure: true, # mark all cookies as "Secure"
  }
end

Это сделает все файлы cookie безопасными в вашем приложении Rails по умолчанию.

Вы также можете добавить эти рекомендуемые конфигурации и установить параметры httponly и samesite:

SecureHeaders::Configuration.default do |config|
  config.cookies = {
    secure: true, # mark all cookies as "Secure"
    httponly: true, # mark all cookies as "HttpOnly"
    samesite: {
      lax: true # mark all cookies as SameSite=lax
    }
  }
end
person K M Rakibul Islam    schedule 07.08.2020

person    schedule
comment
это новая функция в рельсах 4? - person John Bachir; 21.11.2013
comment
Я не знаю. Однако в Rails 4 это работает. Вы также можете проверить это свойство в ВАШЕЙ версии Rails. - person alsotang; 21.11.2013
comment
Это только для файла cookie сеанса, верно? Не для куки вообще? - person Joe Van Dyk; 14.04.2014
comment
Это не работает в Rails 4.1: undefined method 'session_options' for ActionController::Base:Class (NoMethodError) - person jlecour; 14.10.2014
comment
Куда это поставить? - person Palsri; 04.10.2018
comment
apidock.com/rails/ActionController/SessionManagement/ Этот метод устарел или перемещен на последней стабильной версии. Здесь показана последняя существующая версия (v2.3.8). - person cool_php; 02.10.2020