From 243ab5b8176ebd9c80fbf3099459aeb5ec10c229 Mon Sep 17 00:00:00 2001 From: XingQue Date: Wed, 1 Jul 2026 11:36:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20JWT=E8=AE=A4=E8=AF=81=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=97=A7=E7=89=88user=5Fid=20claim=EF=BC=8C=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E5=90=8E=E5=8F=B0401?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- a_long_dianjing/settings.py | 2 +- utils/jwt_auth.py | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 utils/jwt_auth.py diff --git a/a_long_dianjing/settings.py b/a_long_dianjing/settings.py index 37eac54..5d9a703 100644 --- a/a_long_dianjing/settings.py +++ b/a_long_dianjing/settings.py @@ -165,7 +165,7 @@ AUTH_USER_MODEL = 'yonghu.UserMain' # DRF配置(也非常简单) REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework_simplejwt.authentication.JWTAuthentication', + 'utils.jwt_auth.YonghuidJWTAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', diff --git a/utils/jwt_auth.py b/utils/jwt_auth.py new file mode 100644 index 0000000..89e12d1 --- /dev/null +++ b/utils/jwt_auth.py @@ -0,0 +1,39 @@ +""" +自定义 JWT 认证:兼容旧版 token(claim 为 user_id)与新版(claim 为 yonghuid)。 +""" +from django.utils.translation import gettext_lazy as _ +from rest_framework_simplejwt.authentication import JWTAuthentication +from rest_framework_simplejwt.exceptions import AuthenticationFailed, InvalidToken +from rest_framework_simplejwt.settings import api_settings + + +class YonghuidJWTAuthentication(JWTAuthentication): + """签发与校验均以 yonghuid 为准,同时兼容历史 user_id claim。""" + + def get_user(self, validated_token): + user_id, lookup_field = self._resolve_user_identity(validated_token) + if user_id is None: + raise InvalidToken(_('Token contained no recognizable user identification')) + + try: + return self.user_model.objects.get(**{lookup_field: user_id}) + except self.user_model.DoesNotExist as exc: + raise AuthenticationFailed(_('User not found'), code='user_not_found') from exc + + def _resolve_user_identity(self, validated_token): + claim = api_settings.USER_ID_CLAIM + field = api_settings.USER_ID_FIELD + + if claim in validated_token: + return str(validated_token[claim]), field + + legacy_id = validated_token.get('user_id') + if legacy_id is None: + return None, field + + legacy_id = str(legacy_id) + # 旧 token 可能写入主键 id,需回退按 id 查询 + if field != 'id' and legacy_id.isdigit(): + if self.user_model.objects.filter(id=int(legacy_id)).exists(): + return legacy_id, 'id' + return legacy_id, field