django_hosts与Django默认认证功能兼容问题求助
看起来你遇到的是跨域Session/CSRF Cookie共享的典型问题——当你在主域名example.com登录后,session和CSRF cookie默认只绑定在主域名上,导致子域名api.example.com无法识别用户的登录状态,进而表单提交失败;跳回主域名后又能看到已登录,是因为主域名能正常读取这些cookie。下面是具体的解决步骤:
1. 配置共享Cookie的域名
在settings.py里修改以下配置,让所有子域名都能访问session和CSRF cookie:
# 让session cookie对所有子域名生效(注意前面的点) SESSION_COOKIE_DOMAIN = '.example.com' # 同理配置CSRF cookie CSRF_COOKIE_DOMAIN = '.example.com' # 如果是HTTPS部署,建议开启Secure属性,同时设置SameSite为None(非HTTPS环境用Lax) SESSION_COOKIE_SECURE = True # 仅HTTPS环境使用 CSRF_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = 'None' CSRF_COOKIE_SAMESITE = 'None'
注意:本地HTTP开发时,
SESSION_COOKIE_SAMESITE设为'Lax'即可,Secure要设为False,否则浏览器不会保存cookie。
2. 检查django_hosts的中间件顺序
确保django_hosts的中间件在session和auth中间件之前加载,这样Django会先解析子域名,再处理session和认证逻辑:
MIDDLEWARE = [ 'django_hosts.middleware.HostsRequestMiddleware', # 放在最前面 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', # 其他中间件... 'django_hosts.middleware.HostsResponseMiddleware', # 放在最后 ]
3. 确保表单提交的URL是正确的子域名
检查add_post页面的表单action属性,必须指向api.example.com的对应路由,不要使用主域名的URL。推荐用django_hosts的模板标签生成正确的URL:
在模板里:
<form method="post" action="{% host_url 'add_post' host 'api' %}"> {% csrf_token %} <!-- 表单内容 --> </form>
这里的
'api'是你在hosts.py里定义的api子域名的别名,要和你的配置一致。
4. 验证django_hosts的路由配置
确认hosts.py里api子域名的URLconf包含了add_post视图,并且没有拦截认证相关的请求。比如你的hosts.py可能类似:
from django_hosts import patterns, host host_patterns = patterns('', host(r'api', 'myproject.api_urls', name='api'), host(r'', 'myproject.urls', name='default'), )
确保myproject.api_urls里正确配置了add_post的路由,Django的auth中间件能正常处理该子域名的请求。
5. 测试Cookie状态
在浏览器打开api.example.com:8000/add_post,打开开发者工具(F12)的Application标签,查看Cookies列表:
- 确认存在
sessionid和csrftokencookie,且它们的Domain是.example.com - 如果看不到这些cookie,说明前面的配置未生效,检查
settings.py的Cookie配置是否正确
完成这些步骤后,子域名就能读取登录后的session cookie,认证中间件会识别用户状态,CSRF验证也能通过,表单提交就能正常工作了。
内容的提问来源于stack exchange,提问作者smack

