如何将SameSite属性设置为'None;在Rails3.1.12和Ruby1.9.3中“安全”

时间:2019-12-05 12:32:49

标签: ruby-on-rails ruby ruby-on-rails-3.1 ruby-1.9.3 ruby-1.9.2

设置了与https://example.com/处的跨站点资源关联的cookie,但未设置SameSite属性。它已被阻止,因为Chrome现在仅在跨站点请求中将Cookie设置为SameSite=NoneSecure时才发送。您可以在Application> Storage> Cookies下的开发人员工具中查看Cookie,并在https://www.chromestatus.com/feature/5088147346030592https://www.chromestatus.com/feature/5633521622188032上查看更多详细信息。

请让我知道如何设置SameSite cookie属性。提前致谢。

6 个答案:

答案 0 :(得分:5)

在Rails 6.0和6.1中,same_site attribute has been added

sum(order_note like '%garden%')

对于Rails 5.x及更低版本,rails_same_site_cookie gem是将cookies["foo"] = { value: "bar", secure: Rails.application.config.secure_cookies, same_site: "None" } 添加到所有应用程序cookie中的不错选择。它使用中间件来实现。

答案 1 :(得分:4)

动作分派cookies负责将Cookie写入应用程序中设置的浏览器,它使用Rack::Utils.set_cookie_header!

在机架版本1.6之后添加了对SameSite的支持,您需要在Gemfile中检查机架版本,如果机架版本是<1.6,则需要在config/initializers中添加以下代码

require 'rack/utils'
module Rack
  module Utils
    def self.set_cookie_header!(header, key, value)
      case value
      when Hash
        domain  = "; domain="  + value[:domain] if value[:domain]
        path    = "; path="    + value[:path]   if value[:path]
        max_age = "; max-age=" + value[:max_age] if value[:max_age]
        expires = "; expires=" +
          rfc2822(value[:expires].clone.gmtime) if value[:expires]
        secure = "; secure"  if value[:secure]
        httponly = "; HttpOnly" if value[:httponly]
        same_site =
          case value[:same_site]
          when false, nil
            nil
          when :none, 'None', :None
            '; SameSite=None'
          when :lax, 'Lax', :Lax
            '; SameSite=Lax'
          when true, :strict, 'Strict', :Strict
            '; SameSite=Strict'
          else
            raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
          end
        value = value[:value]
      end
      value = [value] unless Array === value
      cookie = escape(key) + "=" +
        value.map { |v| escape v }.join("&") +
        "#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"

      case header["Set-Cookie"]
      when nil, ''
        header["Set-Cookie"] = cookie
      when String
        header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
      when Array
        header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
      end

      nil
    end
  end
end

完成后,您可以在创建新Cookie时设置SameSite属性,例如:

cookies['testing'] = {
  value: 'test',
  path: '/',
  expiry: 1.weeks.from_now,
  same_site: :none
}

您还可以将same_site: <value>添加到会话存储中。

希望这会有所帮助!

答案 2 :(得分:0)

设置自定义标头的方法是将以下行添加到控制器操作中

response.headers['Set-Cookie'] = 'Secure;SameSite=None'

答案 3 :(得分:0)

在这里对机架的修复程序进行了反向移植。

https://github.com/rack/rack/pull/1547

它不会被释放,因此您可能需要在Gemfile中使用叉架。

https://bundler.io/v1.17/guides/git.html

答案 4 :(得分:0)

我所做的是: 在session_store.rb中,我配置了:

MyApp::Application.config.session_store :cache_store, key: COOKIE_NAME, :expire_after => 1.days, :expires_in => 1.days, :domain => 'mydomain.com', same_site: :none

我添加了这个猴子补丁:

require 'rack/utils'
module Rack
  module Utils
    def self.set_cookie_header!(header, key, value)
      case value
      when Hash
        domain  = "; domain="  + value[:domain] if value[:domain]
        path    = "; path="    + value[:path]   if value[:path]
        max_age = "; max-age=" + value[:max_age] if value[:max_age]
        expires = "; expires=" +
            rfc2822(value[:expires].clone.gmtime) if value[:expires]

        # Make it always secure, even in HTTP
        # secure = "; secure"  if value[:secure]
        secure = "; secure"

        httponly = "; HttpOnly" if value[:httponly]
        same_site =
            case value[:same_site]
            when false, nil
              nil
            when :none, 'None', :None
              '; SameSite=None'
            when :lax, 'Lax', :Lax
              '; SameSite=Lax'
            when true, :strict, 'Strict', :Strict
              '; SameSite=Strict'
            else
              raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
            end
        value = value[:value]
      end
      value = [value] unless Array === value
      cookie = escape(key) + "=" +
          value.map { |v| escape v }.join("&") +
          "#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"

      case header["Set-Cookie"]
      when nil, ''
        header["Set-Cookie"] = cookie
      when String
        header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
      when Array
        header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
      end

      nil
    end
  end
end

答案 5 :(得分:0)

Rails 6.0:

cookies[:foo] = {
    value: "bar",
    secure: true,
    same_site: :none
}

您在测试它时必须小心,因为当您运行 HTTPS 时,它仅适用于生产/暂存环境。您将无法在开发过程中对其进行测试。