Добавление SameSite = Нет; куки для Rails через промежуточное ПО Rack? - PullRequest
5 голосов
/ 23 января 2020

4 февраля 2020 года , Google Chrome потребует добавления SameSite=None; ко всем межсайтовым файлам cookie. Rails 6.1 и вскоре Rails 6.0 добавили опцию same_site: :none к рельсу: ie га sh:

cookies["foo"]= {
  value: "bar",
  expires: 1.year.from_now,
  same_site: :none
} 

Но старые приложения Rails 5.x не будут получить обновление, чтобы иметь доступ к same_site опциям га sh. Я знаю, что параметр SameSite=None; cook ie можно вручную добавить в Rails в контроллере с помощью:

response.headers["Set-Cookie"] = "my=cookie; path=/; expires=#{1.year.from_now}; SameSite=None;"

Но в моем приложении Rails 5.x используются сложные объекты cook ie, которые изменяют печенье. Вместо того, чтобы разбивать их на части, я хотел бы написать промежуточное программное обеспечение Rack, чтобы вручную обновлять все куки с атрибутом SameSite=None; сразу.

Этот ответ StackOverflow показывает, как куки могут быть изменены обновить файлы cookie в Rack Middleware:

# lib/same_site_cookie_middleware
class SameSiteCookieMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)
    # confusingly, response takes its args in a different order
    # than rack requires them to be passed on
    # I know it's because most likely you'll modify the body, 
    # and the defaults are fine for the others. But, it still bothers me.

    response = Rack::Response.new body, status, headers

    response.set_cookie("foo", {:value => "bar", :path => "/", :expires => 1.year.from_now, same_site: :none})
    response.finish # finish writes out the response in the expected format.
  end
end
# application.rb
require 'same_site_cookie_middleware'
config.middleware.insert_after(ActionDispatch::Cookies, SameSiteCookieMiddleware)

Как переписать этот код Rack Middleware, чтобы вручную добавить SameSite=None; в каждый существующий повар ie?

Ответы [ 5 ]

2 голосов
/ 01 февраля 2020

Мне удалось заставить это работать со следующими параметрами:

# frozen_string_literals: true

class SameSiteCookies

  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)

    set_cookie_header = headers['Set-Cookie']

    if set_cookie_header && !(set_cookie_header =~ /SameSite\=/)

      headers['Set-Cookie'] << ';' if !(set_cookie_header =~ /;$/)
      headers['Set-Cookie'] << ' SameSite=None'
      headers['Set-Cookie'] << '; Secure' if env['rack.url_scheme'] == 'https';

    end

    [status, headers, body]
  end
end

и добавлением в промежуточное ПО с помощью:

Rails.application.config.middleware.insert_before(ActionDispatch::Cookies, SameSiteCookies)
1 голос
/ 06 марта 2020

Мне удалось заставить все куки использовать SameSite=None по умолчанию для обновления стойки:

gem 'rack', '~> 2.1'

use Rack::Session::Cookie, 
        :httponly     => true,
        :same_site    => :none,
        :secure       => true,
        :secret       => COOKIE_SECRET.to_s()
0 голосов
/ 27 марта 2020

У меня была проблема с зависанием Rails 5 заголовков. Это похоже на ответ Карсона, но обходит эту проблему. Должно работать на оба рельса 5 <и на рельсы 5 +. </p>

# frozen_string_literals: true

class SameSiteCookies

  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)

    set_cookie_header = headers['Set-Cookie']

    if set_cookie_header && !(set_cookie_header =~ /SameSite\=/)
      # the set cookie header variable is frozen
      new_set_cookie_header = set_cookie_header.dup
      new_set_cookie_header << ';' if !(set_cookie_header =~ /;$/)
      new_set_cookie_header << ' SameSite=None'
      new_set_cookie_header << '; Secure' if is_ssl?

      headers['Set-Cookie'] = new_set_cookie_header

    end

    [status, headers, body]
  end

  private

  def is_ssl?
    # custom logic for my application
  end
end

Вставить промежуточное ПО

Rails.application.config.middleware.insert_before(ActionDispatch::Cookies, SameSiteCookies)
0 голосов
/ 03 февраля 2020

Обновление: для Rails 5.x и ниже я нашел гем rails_same_site_cookie хорошим вариантом для добавления SameSite=None; ко всем файлам cookie вашего приложения. Для этого используется промежуточное ПО.

0 голосов
/ 03 февраля 2020

После настройки повара ie вы не можете изменять свойства повара ie, такие как expiry, domain, path.

Браузеры возвращают только имя и значение повара ie как только повар ie уже задан, переопределение любого свойства cook ie создаст нового повара ie. Я бы порекомендовал удалить существующего повара ie и создать нового повара ie с тем же именем и значением.

headers['Set-Cookie'] указывает браузеру создать нового повара ie и изменить его значение в Промежуточное ПО дает вам очень небольшой контроль над значением атрибута.

Я ответил здесь , как этого можно достичь, изменив метод Rack::Utils.set_cookie_header!.

...