Le 4 février 202 , Google Chrome exigera que SameSite=None;
Soit ajouté à tous les cookies intersites. Rails 6.1 et bientôt = Rails 6.0 ont ajouté une option same_site: :none
au hachage de cookie Rails:
cookies["foo"]= {
value: "bar",
expires: 1.year.from_now,
same_site: :none
}
Mais les anciennes applications Rails 5.x) ne recevront pas la mise à jour pour avoir accès au hachage des options same_site
. Je sais que l'option de cookie SameSite=None;
Peut être effectuée manuellement ajouté à Rails dans un contrôleur utilisant:
response.headers["Set-Cookie"] = "my=cookie; path=/; expires=#{1.year.from_now}; SameSite=None;"
Mais mon application Rails 5.x utilise des objets cookies complexes qui modifient les cookies. Au lieu de les séparer, j'aimerais écrire un middleware Rack pour mettre à jour manuellement tous les cookies avec le SameSite=None;
attribut à la fois.
Cette réponse StackOverflow montre comment les cookies peuvent être modifiés pour mettre à jour les cookies dans 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)
Comment réécrire ce code Rack Middleware pour ajouter manuellement SameSite=None;
Dans chaque cookie existant?
Mise à jour: Pour Rails 5.x et inférieurs, j'ai trouvé le Rails_same_site_cookie
gem pour être une bonne option pour ajouter SameSite=None;
à tous les cookies de votre application. Il utilise un middleware pour le faire.
Une fois qu'un cookie est défini, vous ne pouvez pas modifier les propriétés du cookie telles que expiry
, domain
, path
.
Les navigateurs ne renvoient que le nom et la valeur du cookie une fois qu'un cookie a déjà été défini, le remplacement de toute propriété de cookie créera un nouveau cookie. Je recommanderais de supprimer le cookie existant et de créer un nouveau cookie avec le même nom et la même valeur.
headers['Set-Cookie']
demande au navigateur de créer un nouveau cookie et la modification de la valeur dans le middleware vous donne un très petit contrôle sur la valeur de l'attribut.
J'ai répondu ici comment cela peut être réalisé en modifiant le Rack::Utils.set_cookie_header!
méthode.
J'ai eu un problème avec Rails 5 headers étant gelés. Ceci est similaire à la réponse de Carson mais cela contourne ce problème. Devrait fonctionner pour les deux Rails 5 <et 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
Insérez le middleware
Rails.application.config.middleware.insert_before(ActionDispatch::Cookies, SameSiteCookies)