50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""项目自定义认证后端
|
||
|
||
SimpleJWT 的 JWTAuthentication 在 __init__ 中调用 django.contrib.auth.get_user_model(),
|
||
返回 AUTH_USER_MODEL 指定的模型(未配置时为 Django 默认 auth.User)。
|
||
|
||
本项目使用 gvsds.apps.core.models.User 作为用户模型(未设置 AUTH_USER_MODEL),
|
||
因此需要覆盖 user_model,使 JWT 认证查询正确的用户表。
|
||
|
||
同时支持从 Authorization 请求头和 HttpOnly Cookie 读取 JWT,
|
||
以兼容前端基于 Cookie 的认证方式(credentials: 'include')。
|
||
"""
|
||
|
||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||
|
||
from gvsds.apps.core.models import User
|
||
|
||
#: 存储 Access Token 的 Cookie 名称
|
||
JWT_ACCESS_COOKIE = 'AccessToken'
|
||
#: 存储 Refresh Token 的 Cookie 名称
|
||
JWT_REFRESH_COOKIE = 'RefreshToken'
|
||
|
||
|
||
class CustomJWTAuthentication(JWTAuthentication):
|
||
"""JWT 认证——使用项目自定义 User 模型(core.User)
|
||
|
||
优先从 Authorization 请求头读取 token;
|
||
若请求头无 token,则回退到 HttpOnly Cookie(AccessToken)。
|
||
"""
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
super().__init__(*args, **kwargs)
|
||
self.user_model = User
|
||
|
||
def get_header(self, request):
|
||
"""优先从 Authorization 头获取,回退到 Cookie"""
|
||
header = super().get_header(request)
|
||
if header is not None:
|
||
return header
|
||
# 回退:从 Cookie 读取 access token,构造标准 Bearer 头
|
||
cookie_token = request.COOKIES.get(JWT_ACCESS_COOKIE)
|
||
if cookie_token:
|
||
auth_header_types = self.get_auth_header_types()
|
||
prefix = f'{auth_header_types[0]} '.encode('utf-8') if auth_header_types else b''
|
||
return prefix + cookie_token.encode('utf-8')
|
||
return None
|
||
|
||
def get_auth_header_types(self):
|
||
from rest_framework_simplejwt.settings import api_settings
|
||
return api_settings.AUTH_HEADER_TYPES
|