如何基于请求头用户名(无密码)生成DRF认证令牌
解决DRF自定义ObtainAuthToken时用户名字符串无法关联Token的问题
你遇到的报错核心原因是Token.objects.get_or_create(user=user)要求传入User模型实例,但你从请求头拿到的user是字符串类型的用户名,两者类型不匹配。结合你的需求(内部用户无需暴露密码,用令牌调用API并识别调用者),可以通过以下方式解决:
核心思路
- 从请求头提取用户名后,先在系统中查询是否存在对应用户;如果不存在,自动创建一个内部用户(设置不可用的随机密码,避免用户通过该密码登录)
- 使用获取到的User对象来生成或获取唯一Token
修改后的完整代码
from django.contrib.auth.models import User from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.response import Response from django.contrib.auth.hashers import make_random_password class CustomAuthToken(ObtainAuthToken): def get(self, request, *args, **kwargs): # 从请求头获取用户名 username = request.META.get('USERINFO-cn') if not username: return Response({'error': '请求头未携带用户名'}, status=400) # 获取或创建内部用户:自动生成随机密码,确保用户无法通过该密码登录 user, user_created = User.objects.get_or_create( username=username, defaults={'password': make_random_password()} ) # 为用户生成或获取唯一令牌 token, token_created = Token.objects.get_or_create(user=user) return Response({ 'token': token.key, 'username': username, 'user_id': user.id # 返回用户ID,方便后续API识别调用者身份 })
关键说明
- 自动创建用户时使用
make_random_password()生成随机密码,保证内部用户不会通过该密码登录系统,符合“无需暴露密码”的需求 - 额外返回
user_id是为了后续API更精准地识别调用者(用户名可能重复,但用户ID唯一) - 务必确保
USERINFO-cn请求头是经过OAuth2认证后可靠传入的,防止恶意伪造用户名
内容的提问来源于stack exchange,提问作者T rumsey
相关产品推荐
相关产品推荐

