2020年2月4日 、Google Chromeでは、すべてのクロスサイトCookieにSameSite=None;
を追加する必要があります。 Rails 6.1以降Rails 6.0はRails Cookieハッシュにsame_site: :none
オプションを追加しました:
cookies["foo"]= {
value: "bar",
expires: 1.year.from_now,
same_site: :none
}
ただし、古いRails 5.xアプリは、same_site
オプションハッシュにアクセスするためのアップグレードを受け取りません。私はSameSite=None;
cookieオプションを手動でコントローラのRailsに手動で追加できることを知っています:
response.headers["Set-Cookie"] = "my=cookie; path=/; expires=#{1.year.from_now}; SameSite=None;"
しかし、私のRails 5.xアプリは、Cookieを変更する複雑なCookieオブジェクトを使用しています。それらを分解するのではなく、SameSite=None;
属性で一度にすべてのCookieを手動で更新するようにRackミドルウェアを作成したいと思います。
このStackOverflowの回答 は、Rack Middleware内でCookieを更新するようにCookieを変更する方法を示しています。
# 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ミドルウェアコードを書き換えて、既存のCookieにSameSite=None;
を手動で追加するにはどうすればよいですか?
更新:Rails 5.x以下の場合、 _Rails_same_site_cookie
_ gemが良いことがわかりました_SameSite=None;
_をアプリのすべてのCookieに追加するためのオプション。ミドルウェアを使用してそれを行います。
Cookieを設定すると、expiry
、domain
、path
などのCookieプロパティを変更できなくなります。
Cookieがすでに設定されている場合、ブラウザはCookieの名前と値のみを返します。Cookieプロパティを上書きすると、新しいCookieが作成されます。既存のCookieを削除し、同じ名前と値で新しいCookieを作成することをお勧めします。
headers['Set-Cookie']
は、ブラウザに新しいCookieを作成するように指示し、ミドルウェアで値を変更しても、属性値をほとんど制御できません。
私は答えました hereRack::Utils.set_cookie_header!
メソッドを変更することでこれをどのように実現できるか。
Rails 5ヘッダーがフリーズする問題がありました。これはCarsonの回答に似ていますが、この問題を回避します。Rails 5 <とRails 5+。
# 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)