You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7+Devise实现仅两子域共享Cookie,其余子域独立Cookie

解决方案

1. 修改基础Session配置

首先调整config/initializers/session_store.rb,移除固定的domain配置,只保留基础的session store初始化:

Rails.application.config.session_store :cookie_store, key: "_myapp_session"

2. 编写动态Session配置中间件

创建app/middleware/dynamic_session_config_middleware.rb,根据请求子域动态切换Cookie规则:

class DynamicSessionConfigMiddleware
  def initialize(app)
    @app = app
    # 定义需要共享Cookie的子域
    @shared_subdomains = ["www", "dashboard"]
    # 根据环境设置根域名(开发环境可替换为lvh.me方便测试子域)
    @root_domain = Rails.env.production? ? "my-site.com" : "lvh.me"
  end

  def call(env)
    request = Rack::Request.new(env)
    current_host = request.host
    # 提取当前请求的子域部分
    current_subdomain = current_host.split('.')[0...-2].join('.')

    if @shared_subdomains.include?(current_subdomain)
      # 共享子域:设置根域名,让www和dashboard共享Cookie
      env["rack.session.options"][:domain] = ".#{@root_domain}"
      env["rack.session.options"][:tld_length] = 2
      env["rack.session.options"][:key] = "_myapp_session"
    else
      # 自定义子域:设置Cookie仅在当前子域有效
      env["rack.session.options"][:domain] = current_host
      # 使用独立的session key避免与共享域冲突
      env["rack.session.options"][:key] = "_myapp_session_#{current_subdomain.gsub('.', '_')}"
      env["rack.session.options"].delete(:tld_length)
    end

    # 同步处理Devise的"记住我"Cookie配置
    if defined?(Devise)
      devise_scope = Devise.mappings.values.first
      next unless devise_scope

      remember_cookie_key = "#{devise_scope.name}_remember_token"
      cookie_options = env["rack.session.options"][:cookies][remember_cookie_key] ||= {}

      if @shared_subdomains.include?(current_subdomain)
        cookie_options[:domain] = ".#{@root_domain}"
        cookie_options[:tld_length] = 2
      else
        cookie_options[:domain] = current_host
        cookie_options.delete(:tld_length)
      end
    end

    @app.call(env)
  end
end

3. 注册中间件

在config/application.rb中添加中间件注册,确保它在Rails的Session中间件之前执行:

module MyApp
  class Application < Rails::Application
    # ...其他现有配置
    # 插入动态Session配置中间件
    config.middleware.insert_before ActionDispatch::Session::CookieStore, DynamicSessionConfigMiddleware
  end
end

4. 调整Devise配置

打开config/initializers/devise.rb,移除硬编码的rememberable domain配置(如果有的话),让中间件动态控制:

# 确保没有固定的domain设置,改为空哈希
config.rememberable_options = {}

验证逻辑

  • 用户在www.my-site.com注册/登录后,Cookie会被设置为根域名.my-site.com,重定向到dashboard.my-site.com时能自动保持登录状态。
  • 自定义子域(如a-customer-subdomain.my-site.com)的请求会生成独立的Cookie,仅在该子域有效,不会与www/dashboard或其他自定义子域共享会话。

内容的提问来源于stack exchange,提问作者D-Nice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:55:07