Django SessionID刷新后消失:跨域NextJS前端会话问题排查
场景
使用搭载SessionAuthentication的Django DRF后端(HTTPS,端口8000)与NextJS前端(HTTPS,端口3000)跨端口部署。尝试通过Django的login函数实现用户注册后自动登录,执行后sessionid与CSRF Cookie已存入浏览器,但页面刷新后这些Cookie消失。
现象
- 刷新前:浏览器开发者工具中可查到
sessionid和CSRF Cookie - 刷新后:上述Cookie完全消失
后端配置(settings.py)
CORS_ALLOW_CREDENTIALS = True CSRF_USE_SESSIONS = True SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = 'None' CORS_ALLOWED_ORIGINS = [ "https://localhost:3000", ] CSRF_TRUSTED_ORIGINS = { "https://localhost:3000" }
后端视图代码
class UserView(APIView): renderer_classes = [JSONRenderer] permission_classes = [ permissions.AllowAny ] decorators = [sensitive_variables('password'), ensure_csrf_cookie] @method_decorator(decorators) def post(self, request, format=None): """Create User""" serializer = UserSerializer(data=request.data) if serializer.is_valid(): serializer.save() username = serializer.validated_data['username'] password = serializer.validated_data['password'] user = authenticate(username=username, password=password) if user: login(request, user) return Response(data={'response': 'Successfully created account'}, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
前端请求代码
const response = await fetch(`https://127.0.0.1:8000/user/`, { method: 'POST', mode: 'cors', credentials: 'include', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) });
环境说明
Django服务器与NextJS均使用开发SSL证书,均为HTTPS协议。
解决方案
1. 修正CSRF_TRUSTED_ORIGINS格式
Django要求CSRF_TRUSTED_ORIGINS为列表类型,当前使用集合会导致配置失效,修改为:
CSRF_TRUSTED_ORIGINS = [ "https://localhost:3000", ]
2. 统一域名/IP地址
前端请求用127.0.0.1,但配置信任的是localhost,浏览器会将二者视为不同域名,导致Cookie无法保留。把前端请求地址改为:
const response = await fetch(`https://localhost:8000/user/`, { // 原有参数不变 });
3. 补充CSRF Cookie的安全配置
仅配置Session Cookie的SameSite是不够的,需单独设置CSRF Cookie的规则:
CSRF_COOKIE_SAMESITE = 'None' CSRF_COOKIE_SECURE = True
4. 调整装饰器写法确保生效
当前装饰器组合写法可能存在优先级问题,拆分后更稳妥:
class UserView(APIView): renderer_classes = [JSONRenderer] permission_classes = [permissions.AllowAny] @method_decorator(sensitive_variables('password')) @method_decorator(ensure_csrf_cookie) def post(self, request, format=None): // 原有业务代码不变
5. 明确Session Cookie的Domain
添加配置指定Cookie的绑定域名,避免浏览器自动判断错误:
SESSION_COOKIE_DOMAIN = 'localhost'
内容的提问来源于stack exchange,提问作者24Chromosones
相关产品推荐
相关产品推荐

