将DRF的Auth Token存入HttpOnly Cookie的方案是否合理?
实现背景与做法
为避免前端不安全存储access_token,基于Djoser框架做了以下改造:
- 重写
TokenCreateView,将生成的access_token存入HttpOnly Cookie,不直接返回给前端 - 编写中间件,自动从Cookie中读取access_token并注入到请求头的
Authorization字段,兼容后端原有Token认证逻辑
重写的TokenCreateView代码
from djoser.views import TokenCreateView class TokenCreateView(TokenCreateView): def _action(self, serializer): token = utils.login_user(self.request, serializer.user) token_serializer_class = settings.SERIALIZERS.token response = Response() data = token_serializer_class(token).data response.set_cookie( key = 'access_token', value = data['auth_token'], secure = False, httponly = True, samesite = 'Lax' ) response.data = {"Success" : "Login successfully","data":data} return response
认证中间件代码
def auth_token(get_response): def middleware(request): # when token is in headers in is not needed to add in from cookies logger.error(request.COOKIES.get('access_token')) if 'HTTP_AUTHORIZATION' not in request.META: token = request.COOKIES.get('access_token') if token: request.META['HTTP_AUTHORIZATION'] = f'Token {token}' return get_response(request) return middleware MIDDLEWARE = [ ... 'apps.profiles.middlewares.auth_token', ... ]
方案优势
- XSS防护能力提升:HttpOnly Cookie禁止前端JS读取,从根源上避免了XSS攻击导致的token窃取风险
- 前端开发简化:无需前端手动存储、携带token,所有token传递逻辑由浏览器自动完成,降低开发复杂度
- 后端兼容性好:通过注入标准的
Authorization头,完全复用原有TokenAuthentication逻辑,不需要修改后端认证核心代码
需要优化的细节
- 强制开启secure属性:生产环境必须将
secure设为True,确保Cookie仅通过HTTPS传输,防止明文网络环境下的token泄露 - 添加Cookie有效期:建议设置
max_age或expires参数,限制token的有效时长;同时建议配套实现refresh_token机制(存入另一个HttpOnly Cookie),实现无感知续期 - 清理调试代码:移除中间件中的
logger.error调试代码,避免生产环境日志冗余 - 优化中间件逻辑:增加token格式校验(比如检查是否符合Token格式),避免非法Cookie值干扰认证流程
- 完善登出逻辑:登出接口需要主动清除
access_tokenCookie,确保用户退出后token立即失效 - 适配跨域场景:如果是跨域项目,需将
SameSite设为None并配合secure=True,同时确保后端配置了正确的跨域Cookie允许策略
总结
这个方案的核心思路符合前端无敏感token存储的安全最佳实践,整体是合理且可行的。只要补上上述优化点,就能在生产环境中稳定、安全地使用。
内容的提问来源于stack exchange,提问作者Anna_Silchenko
相关产品推荐
相关产品推荐

