fix: JWT 用户缓存避免每请求查库 + 移除全 API 限流
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""自定义 JWT 认证 — 向后兼容旧 token 的 user_id claim"""
|
||||
|
||||
from django.core.cache import cache
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed
|
||||
from rest_framework_simplejwt.settings import api_settings
|
||||
@@ -16,28 +17,29 @@ class CompatibleJWTAuthentication(JWTAuthentication):
|
||||
值为 user.UserUID(7位业务ID)。
|
||||
|
||||
此类先尝试新 claim,找不到时回退到旧 claim,并用对应字段查库。
|
||||
用户对象缓存 300 秒(Redis),避免每个 API 都打一次 MySQL。
|
||||
"""
|
||||
|
||||
def get_user(self, validated_token):
|
||||
# 1. 先尝试当前配置的 USER_ID_CLAIM
|
||||
user_id = validated_token.get(api_settings.USER_ID_CLAIM)
|
||||
lookup_field = api_settings.USER_ID_FIELD
|
||||
|
||||
if user_id is None:
|
||||
# 2. 回退:尝试旧 token 中的 'user_id' claim
|
||||
user_id = validated_token.get('user_id')
|
||||
if user_id is None:
|
||||
raise InvalidToken(
|
||||
{'detail': _('令牌未包含用户标识符'), 'code': 'token_not_valid'}
|
||||
)
|
||||
# 旧 token 的 user_id 来自 user.id(即 UserUUID),
|
||||
# 需要用 UserUUID 字段查库
|
||||
lookup_field = 'UserUUID'
|
||||
|
||||
try:
|
||||
user = self.user_model.objects.get(**{lookup_field: user_id})
|
||||
except self.user_model.DoesNotExist:
|
||||
raise AuthenticationFailed(_('用户不存在'), code='user_not_found')
|
||||
cache_key = f'jwt_user:{lookup_field}:{user_id}'
|
||||
user = cache.get(cache_key)
|
||||
if user is None:
|
||||
try:
|
||||
user = self.user_model.objects.get(**{lookup_field: user_id})
|
||||
except self.user_model.DoesNotExist:
|
||||
raise AuthenticationFailed(_('用户不存在'), code='user_not_found')
|
||||
cache.set(cache_key, user, 300)
|
||||
|
||||
if not user.is_active:
|
||||
raise AuthenticationFailed(_('用户已被禁用'), code='user_inactive')
|
||||
|
||||
Reference in New Issue
Block a user