refactor(auth): JWT 认证链路复用 SDK ResolveRoleContext,消除角色解析双实现
This commit is contained in:
1 parent
9f1b222bfe
commit
e0af444c31
1 file changed
+4
-66
+4
-66
@@ -9,18 +9,16 @@ SimpleJWT 的 JWTAuthentication 在 __init__ 中调用 django.contrib.auth.get_u
|
||||
同时支持从 Authorization 请求头和 HttpOnly Cookie 读取 JWT,
|
||||
以兼容前端基于 Cookie 的认证方式(credentials: 'include')。
|
||||
|
||||
额外职责:JWT 认证成功后立即解析当前角色上下文(current_role / current_company_uuid /
|
||||
current_tenant_uuid),填充到 request 对象。这解决了 Django 中间件在 DRF 认证之前运行、
|
||||
额外职责:JWT 认证成功后立即解析当前角色上下文(ResolveRoleContext,
|
||||
唯一实现位于 gvsdsdk.auth.middleware,与 CurrentRoleMiddleware 共用)。
|
||||
这解决了 Django 中间件在 DRF 认证之前运行、
|
||||
导致中间件无法获取已认证用户的问题。
|
||||
"""
|
||||
|
||||
import logging
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
|
||||
from gvsds.apps.core.models import User
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
from gvsdsdk.auth.middleware import ResolveRoleContext
|
||||
|
||||
#: 存储 Access Token 的 Cookie 名称
|
||||
JWT_ACCESS_COOKIE = 'AccessToken'
|
||||
@@ -28,66 +26,6 @@ JWT_ACCESS_COOKIE = 'AccessToken'
|
||||
JWT_REFRESH_COOKIE = 'RefreshToken'
|
||||
|
||||
|
||||
def ResolveRoleContext(request, user):
|
||||
"""解析当前角色上下文,填充 request.current_role / current_company_uuid / current_tenant_uuid
|
||||
|
||||
从 CurrentRoleUUID Cookie 读取角色 UUID,查询 UserRole + Role,
|
||||
设置 request.current_role / current_company_uuid / current_tenant_uuid。
|
||||
|
||||
Args:
|
||||
request: HTTP 请求对象(会被原地修改)
|
||||
user: 已认证的 User 实例
|
||||
"""
|
||||
# 确保默认值(防止重复调用时残留旧值)
|
||||
request.current_role = None
|
||||
request.current_company_uuid = None
|
||||
request.current_tenant_uuid = None
|
||||
|
||||
if not user or not getattr(user, 'is_authenticated', False):
|
||||
if hasattr(user, 'IsAuthenticated'):
|
||||
if not user.IsAuthenticated:
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
from gvsdsdk.models import UserRole, Role
|
||||
from gvsdsdk.model_utils import UUIDObj
|
||||
|
||||
role_uuid_str = request.COOKIES.get('CurrentRoleUUID', '')
|
||||
if not role_uuid_str:
|
||||
_logger.warning('[ResolveRoleContext] 已认证用户 %s 无 CurrentRoleUUID cookie', user)
|
||||
return
|
||||
|
||||
try:
|
||||
role_uuid_bytes = UUIDObj(role_uuid_str).bytes
|
||||
user_role = UserRole.objects.filter(
|
||||
UserUUID=user.UserUUID,
|
||||
RoleUUID=role_uuid_bytes
|
||||
).first()
|
||||
if not user_role:
|
||||
_logger.warning('[ResolveRoleContext] cookie=%s 但 UserRole 未找到 (user=%s)',
|
||||
role_uuid_str[:36], user)
|
||||
return
|
||||
# 单独查询 Role 实例(Role.TenantUUID 提供租户信息)
|
||||
role = Role.objects.filter(RoleUUID=role_uuid_bytes).first()
|
||||
if role:
|
||||
request.current_role = role
|
||||
# 从 Role 实例获取租户 UUID(UUIDObj,FormService 会转 bytes)
|
||||
request.current_tenant_uuid = role.TenantUUID
|
||||
# UserRole.CompanyUUID 是 UUIDField,直接赋值
|
||||
if user_role.CompanyUUID:
|
||||
request.current_company_uuid = user_role.CompanyUUID
|
||||
_logger.info('[ResolveRoleContext] cookie=%s, role=%s, tenant=%s, company=%s',
|
||||
role_uuid_str[:36],
|
||||
getattr(role, 'RoleName', None) if role else None,
|
||||
request.current_tenant_uuid,
|
||||
request.current_company_uuid)
|
||||
except (ValueError, KeyError, ObjectDoesNotExist) as e:
|
||||
_logger.warning('[ResolveRoleContext] cookie=%s 解析失败: %s', role_uuid_str[:36], e)
|
||||
except Exception:
|
||||
_logger.exception('[ResolveRoleContext] 解析当前角色失败')
|
||||
|
||||
|
||||
class CustomJWTAuthentication(JWTAuthentication):
|
||||
"""JWT 认证——使用项目自定义 User 模型(core.User)
|
||||
|
||||
|
||||
Reference in new issue
Block a user