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

自定义登录系统中如何获取User实例?

问题分析与解决方案

核心问题

  1. 认证类缺失:视图未配置TokenAuthentication,导致DRF无法解析请求头中的Token,request.user始终为匿名用户
  2. 登录逻辑错误:登录接口中错误使用匿名的request.user判断Token是否存在,逻辑完全不成立
  3. 状态处理逻辑不清晰:未明确区分登录/未登录状态下的API处理方式

代码修正步骤

1. 补充TokenAuthentication认证类

修改login.py中Endpoint类的authentication_classes,添加TokenAuthentication,让DRF能解析请求头里的Token:

class Endpoint(APIView):
    authentication_classes = [BasicAuthentication, SessionAuthentication, TokenAuthentication]
    permission_classes = [AllowAny]

    def post(self, request: Request):
        # ... 原有代码 ...

2. 修复Login函数的逻辑错误

登录接口是未登录用户获取Token的入口,此时request.user是匿名用户,不能用它判断Token存在性。应先根据传入的账号/邮箱查询用户,再判断该用户是否已有Token:

def Login(request: Request, id: str, password: str) -> dict[str, str]:
    # -------------------------------
    # Check and Format Data
    # -------------------------------
    if not contains(request, id, password):
        raise Error("ulxdQrfrP2")

    # -------------------------------------
    # Execute Queries and Perform
    # -------------------------------------
    try:
        user: User = User.objects.filter(
            Q(account_name__exact = id) | Q(email__exact = id)
        ).get()

        # 检查该用户是否已有Token
        if Token.objects.filter(user=user).exists():
            raise Error("SwZu4K4N1p", message="Token already exists")

        # 校验密码并生成Token
        if bcrypt.checkpw(password.encode("UTF8"), user.password.encode("UTF8")):
            token: Token = Token.objects.create(user = user)
            return { "token": token.key }
        else:
            raise Error("tSqmORm1y5", 404, "empty", "No record found with inserted inputs")

    except User.DoesNotExist:
        raise Error("h0lddS4Jtn", 404, "empty", "No record found with inserted inputs")
    except Exception as e:
        print(f"\n{str(e)}\n")
        raise Error("SwZu4K4N1p", message="Token already exists")

3. 支持登录/未登录状态的API处理

对于需要同时兼容两种状态的API,保持permission_classes = [AllowAny],在视图中通过request.user.is_authenticated判断状态:

class SomeAPIView(APIView):
    authentication_classes = [TokenAuthentication, SessionAuthentication]
    permission_classes = [AllowAny]

    def get(self, request: Request):
        if request.user.is_authenticated:
            # 已登录逻辑:可直接访问request.user.id
            return API_CallBack({"user_id": request.user.id})
        else:
            # 未登录逻辑
            return API_CallBack({"message": "未登录状态"})

4. 密码存储校验(关键注意点)

确保User模型中password字段存储的是bcrypt哈希后的字符串,而非明文。创建用户时需正确哈希:

# 示例:创建用户时的密码处理
import bcrypt

def create_user(account_name, email, password):
    password_hash = bcrypt.hashpw(password.encode('utf8'), bcrypt.gensalt())
    user = User.objects.create(
        account_name=account_name,
        email=email,
        password=password_hash.decode('utf8')  # 存储字符串格式的哈希值
    )
    return user

验证步骤

  1. 用Postman发送登录请求,获取Token
  2. 在需要验证的API请求头中携带Authorization: Token 你的Token值
  3. 打印request.user,此时应能正确获取到User实例,且request.user.id可正常访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:30:33