web-dev-qa-db-fra.com

Ajout de «SameSite = None;» cookies à Rails via le middleware Rack?

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?

5
Kelsey Hannan

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.

0
Kelsey Hannan

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.

0
anil.n

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)
0
cesartalves