- P0/P1 审计修复: 滑块验证码不再下发 x_position/成败即销毁 key、 user-login 补失败计数+滑块门控、限流标识改 X-Real-IP、 百度翻译 appkey 环境化、ChangeEmail/ChangePhone 补调 avalidate、 logs/tasks.py Count(filter=Q) 修复、chat 收藏 SSRF 内网黑名单 - P1 #6/7: token_blacklist + ROTATE_REFRESH_TOKENS 开启, /user/token/refresh/ 挂载 - #2 JWT HttpOnly Cookie 双模认证: user/cookie_auth.py 种/清 Cookie, user/authentication.py CookieOrHeaderJWTAuthentication(Bearer 优先/_COOKIE 兜底), user/views/token.py CookieTokenRefreshView + UserLogoutAPIView(/user/logout/), create_standardized_response 自动对含 token 的响应种 Cookie, 异步视图内 RefreshToken.for_user 全部 sync_to_async 包裹(修 SynchronousOnlyOperation 500), WS ChatConsumer 优先读 Cookie token - P2 #11 限流: utils/rate_limit.py 固定窗口频控, shorturl 生成 匿名10次/分+登录60次/分, 邮箱验证码 同邮箱60s1次+同IP10次/10min, 登录/注册验证码 错5次作废+成功即销毁防重放, 换绑邮箱/手机 同步落地, urls.py 补挂 shorturl 路由(此前 404)
25 lines
953 B
Python
25 lines
953 B
Python
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||
|
||
|
||
class CookieOrHeaderJWTAuthentication(JWTAuthentication):
|
||
"""
|
||
双模 JWT 认证器:
|
||
1. 优先从 HTTP Authorization 头读取 Bearer Token(移动端 Android / iOS / API 客户端);
|
||
2. 若 Authorization 头不存在,则从 HttpOnly Cookie 中读取 access_token(Web 端,杜绝 XSS 窃取)。
|
||
"""
|
||
def authenticate(self, request):
|
||
header = self.get_header(request)
|
||
if header is not None:
|
||
raw_token = self.get_raw_token(header)
|
||
else:
|
||
# 从 HttpOnly Cookie 读取 access_token
|
||
raw_token = request.COOKIES.get('access_token')
|
||
if raw_token:
|
||
raw_token = raw_token.encode('utf-8')
|
||
|
||
if raw_token is None:
|
||
return None
|
||
|
||
validated_token = self.get_validated_token(raw_token)
|
||
return self.get_user(validated_token), validated_token
|