django-rest-framework中HttpOnly Cookie的令牌如何传入Authorization头
实现方案
因为你把令牌存在了HttpOnly Cookie中,前端JavaScript无法直接读取令牌值,所以没办法手动往请求头加Authorization字段,需要修改后端认证逻辑,直接从Cookie中读取令牌完成校验,具体实现步骤如下:
步骤1:自定义Knox认证类
继承Knox原生的TokenAuthentication类,重写令牌获取逻辑,优先从Cookie中读取auth_token值:
from knox.auth import TokenAuthentication from rest_framework import HTTP_HEADER_ENCODING, exceptions class CookieTokenAuthentication(TokenAuthentication): def get_authorization_token(self, request): # 优先从Cookie中取令牌 auth_token = request.COOKIES.get('auth_token', None) if auth_token: return auth_token.encode(HTTP_HEADER_ENCODING) # 兼容原有Header传递的场景,不需要可以删掉 auth_header = request.META.get('HTTP_AUTHORIZATION', b'') if isinstance(auth_header, str): auth_header = auth_header.encode(HTTP_HEADER_ENCODING) if not auth_header: return None try: auth_type, token = auth_header.split() except ValueError: raise exceptions.AuthenticationFailed('无效的认证头格式') if auth_type.lower() != b'token': return None return token def authenticate(self, request): token = self.get_authorization_token(request) if not token: return None return self.authenticate_credentials(token)
步骤2:配置DRF认证规则
你可以选择全局生效或者指定视图生效:
- 全局生效:修改项目
settings.py中的DRF配置
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( '你的应用路径.authentication.CookieTokenAuthentication', # 替换成你刚才写的认证类实际路径 ), # 其他原有配置保留 }
- 单视图生效:在需要认证的视图类中指定
authentication_classes
from rest_framework.views import APIView from 你的应用路径.authentication import CookieTokenAuthentication class 你的受保护视图(APIView): authentication_classes = (CookieTokenAuthentication,) # 其他视图逻辑
步骤3:跨域适配(前后端不同源时需要配置)
如果你的React前端和Django后端域名/端口不同,需要做如下配置:
- 安装
django-cors-headers后,修改settings.py:
# 允许携带Cookie CORS_ALLOW_CREDENTIALS = True # 允许的前端源地址,不要填* CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", # 替换成你的React前端实际访问地址 ]
- 前端请求配置:
- axios:全局配置请求时携带Cookie
axios.defaults.withCredentials = true
- fetch:每次请求带上
credentials: 'include'参数
fetch(url, { credentials: 'include', // 其他请求配置 })
步骤4:可选优化:登出接口清理Cookie
你可以重写Knox的登出视图,调用后清空auth_token Cookie,避免令牌残留:
from knox.views import LogoutView as KnoxLogoutView class LogoutView(KnoxLogoutView): def post(self, request, format=None): response = super().post(request, format=None) response.delete_cookie('auth_token') return response
内容的提问来源于stack exchange,提问作者Fady's Cube
相关产品推荐
相关产品推荐

