You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求中Access Token自动变更问题排查求助

问题

我通过以下代码实现登录接口,获取Access Token和Refresh Token:

class Employee_Login(APIView):
permission_classes=[AllowAny]
employee_login_data = serializers.employee_login_serializer

def post(self,request):
    try:
        employee_data = self.employee_login_data(data=request.data)
        employee_data.is_valid(raise_exception=True)
        data = employee_data.validated_data

        employee = authenticate(request,email=data.get('email'), password= data.get('password'))

        if not employee:
            return Http404("Employee not found")
        
        if not employee.is_verified:
            raise ForbiddenException("Employee is not verified")
        
        payloads = {
            "user": "admin" if employee.is_admin and employee.is_verified and employee.is_staff
                    else "staff" if employee.is_staff and employee.is_verified
                    else ""
        }

        employee_detail = {
            "name":employee.name,
            "email":employee.email,
            "type":"admin" if employee.is_admin and employee.is_staff and employee.is_verified 
                        else "staff" if employee.is_admin and employee.is_verified
                        else ""
        }

        refresh = RefreshToken.for_user(employee)
        refresh.payload.update(payloads)

        acess_token = str(refresh.access_token)
        refresh_token = str(refresh)

        return Response({"success":True, 
                         "data":employee_detail, 
                         "token":{"access":acess_token,"refresh":refresh_token}})
    except Exception as e:
        return Response({"success":False,"message":str(e)})

但将获取到的Access Token用于以下自定义权限类时,出现异常:

class AdminPermission(permissions.BasePermission):
def has_permission(self, request, view):

    print("Here",AccessToken(request.auth).payload)
    
    STAFF_METHODS = ['GET','POST','PATCH']
    USER_METHODS = ['GET']
    
    if request.method in USER_METHODS:
        return True
    
    print(AccessToken(request.auth))
        
    if request.user.is_authenticated:
    
        if request.user.is_admin and request.user.is_staff and request.user.is_verified:
            return True
        
        if not request.user.is_admin and request.user.is_staff and request.user.is_verified and request.method in STAFF_METHODS: 
            return True
    
    return False

print(AccessToken(request.auth))打印出的Token和请求中传入的完全不同,而且每次请求打印的内容都不一样,找不到问题所在,请求帮助。

解决方案

问题根源

Django REST Framework的JWT认证后端(如rest_framework_simplejwt)会自动解析请求中的Token,将request.auth设置为已解析完成的Token对象,而非原始的Token字符串。当你调用AccessToken(request.auth)时,相当于用已解析的payload重新生成了一个新的AccessToken,所以每次打印的内容都会变化。

修复步骤

  1. 获取原始Token字符串:如果需要查看请求传入的原始Token,直接从请求头中提取,不要使用AccessToken()包裹request.auth:
# 从Authorization头提取原始Token
raw_token = request.META.get('HTTP_AUTHORIZATION', '').split(' ')[-1]
print(raw_token)
  1. 正确使用已解析的Token对象:request.auth本身就是解析后的AccessToken实例,直接访问其属性即可:
# 直接获取payload
print("Here", request.auth.payload)
# 打印当前Token的字符串形式
print(str(request.auth))
  1. 优化权限类逻辑:原代码中if request.method in USER_METHODS: return True会让所有GET请求直接跳过权限校验,这可能不符合预期,建议调整逻辑顺序:
class AdminPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        STAFF_METHODS = ['GET','POST','PATCH']
        
        # 未登录用户直接拒绝
        if not request.user.is_authenticated:
            return False
        
        # 管理员拥有全量权限
        if request.user.is_admin and request.user.is_staff and request.user.is_verified:
            return True
        
        # 普通员工仅允许指定请求方法
        if request.user.is_staff and request.user.is_verified and request.method in STAFF_METHODS:
            return True
        
        return False

内容的提问来源于stack exchange,提问作者Roshan Ojha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:07:33