自定义登录系统中如何获取User实例?
问题分析与解决方案
核心问题
- 认证类缺失:视图未配置
TokenAuthentication,导致DRF无法解析请求头中的Token,request.user始终为匿名用户 - 登录逻辑错误:登录接口中错误使用匿名的
request.user判断Token是否存在,逻辑完全不成立 - 状态处理逻辑不清晰:未明确区分登录/未登录状态下的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
验证步骤
- 用Postman发送登录请求,获取Token
- 在需要验证的API请求头中携带
Authorization: Token 你的Token值 - 打印
request.user,此时应能正确获取到User实例,且request.user.id可正常访问
内容的提问来源于stack exchange,提问作者aman
相关产品推荐
相关产品推荐

