单个Flask应用多子域名独立登录会话实现方案咨询
解决方案
这里有两个落地成本极低的可行方案,你可以根据自己的业务情况选择:
方案1:动态配置独立session cookie(推荐优先使用)
这个方案完全不需要修改现有业务逻辑,仅需添加一个全局前置钩子,为每个子域名分配独立的session cookie,从根源上避免cookie复用:
- 移除配置文件中硬编码的
SESSION_COOKIE_DOMAIN、SESSION_COOKIE_NAME、REMEMBER_COOKIE_NAME相关配置 - 添加全局
before_request钩子,根据当前访问的子域名动态设置cookie参数:
from flask import request, app @app.before_request def dynamic_cookie_config(): # 提取当前子域名,本地测试场景可自行适配规则 host_parts = request.host.split(':')[0].split('.') if len(host_parts) >=3: subdomain = host_parts[0] else: subdomain = 'local' # 每个子域名使用独立的cookie名称,彻底避免跨子域复用 app.config['SESSION_COOKIE_NAME'] = f'session_{subdomain}' # 明确绑定cookie到当前完整域名,禁止跨子域传递 app.config['SESSION_COOKIE_DOMAIN'] = request.host.split(':')[0] # 同步配置flask-login的remember cookie保持独立 app.config['REMEMBER_COOKIE_NAME'] = f'remember_{subdomain}'
配置完成后,www.domain.com和workers.domain.com会生成完全独立的两套cookie,互不干扰,同一浏览器下可以同时登录两个身份的账号。
方案2:session内容加子域名校验(可选,作为双重保险)
如果担心存在历史遗留的泛域名cookie导致串站,可以再加一层session内容校验,即使cookie意外串用也不会引发业务问题:
- 在两个子域名的登录逻辑中,登录成功后把当前子域名写入session:
# 面向客户站点的登录逻辑 @customers.route('/login', methods=['POST']) def login(): # 账号密码校验逻辑省略 session['bind_subdomain'] = 'www' login_user(user) # 后续逻辑省略 # 面向员工站点的登录逻辑 @workers.route('/login', methods=['POST']) def login(): # 账号密码校验逻辑省略 session['bind_subdomain'] = 'workers' login_user(user) # 后续逻辑省略
- 添加全局前置钩子,校验当前访问子域名和session中绑定的子域名是否一致:
@app.before_request def check_session_subdomain(): # 放行静态资源、登录接口等无需校验的请求 exclude_endpoints = ['customers.login', 'workers.login', 'static'] if request.endpoint in exclude_endpoints: return current_subdomain = request.host.split('.')[0] # 子域名不匹配时清空session,跳转到对应登录页 if 'bind_subdomain' in session and session['bind_subdomain'] != current_subdomain: session.clear() return redirect(url_for(f'{current_subdomain}.login'))
关于你提到的两个思路说明
- 为不同子域名设置不同
SECRET_KEY的方案需要重写Flask的session加密逻辑,落地成本较高,没有必要优先选择 - 重写session逻辑将子域名和用户ID绑定加密的方案和方案2的效果一致,但改造成本更高,不如方案2简单直接
内容的提问来源于stack exchange,提问作者Ibraheem Alyan
相关产品推荐
相关产品推荐

