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
相关产品推荐
相关产品推荐

