DRF自定义认证场景POST请求提示凭证未提供的解决方法
问题排查与解决步骤
1. 修正请求头设置(核心问题)
你在Postman中设置的请求头键错误,导致Django无法获取到用户名:
- 错误做法:设置键为
HTTP_USERNAME - 正确做法:将请求头键改为
Username(不带HTTP_前缀),值填写后台创建的用户名。
原因:Django会自动将请求头转换为HTTP_<大写键名>的格式存入request.META。比如你发送Username: testuser,Django会在request.META中生成HTTP_USERNAME: testuser;如果直接发送HTTP_USERNAME: testuser,Django会生成HTTP_HTTP_USERNAME: testuser,你的认证类自然拿不到值,返回None导致认证失败。
2. 验证认证类的取值逻辑
可以在CustomAuthentication的authenticate方法中添加调试代码,确认是否能正确获取到用户名:
class CustomAuthentication(authentication.BaseAuthentication): def authenticate(self, request): # 打印所有META键,确认是否存在HTTP_USERNAME print(request.META.keys()) username = request.META.get('HTTP_USERNAME') if not username: return None try: user = User.objects.get(username=username) except User.DoesNotExist: raise exceptions.AuthenticationFailed('No such user') return (user, None)
运行Django服务后,发起POST请求,查看控制台输出是否包含HTTP_USERNAME,以此确认请求头是否正确传递。
3. 修复模型缺失的user字段
你的OpeningHours模型中没有定义user字段,但序列化器和视图中都用到了这个字段,后续保存数据时会报错,需要补充:
# models.py from django.contrib.auth.models import User class OpeningHours(models.Model): # 添加user外键关联 user = models.ForeignKey(User, on_delete=models.CASCADE) day_of_week = models.IntegerField(choices=((0, 'Sunday'), (1, 'Monday'), (2, 'Tuesday'), (3, 'Wednesday'), (4, 'Thursday'), (5, 'Friday'), (6, 'Saturday'))) opening_time = models.TimeField() closing_time = models.TimeField()
添加后记得执行数据库迁移命令:
python manage.py makemigrations python manage.py migrate
4. 确认权限类配置
你使用的permissions.IsAuthenticatedOrReadOnly权限类符合需求:它允许认证用户执行POST/PUT/DELETE等写操作,未认证用户只能执行GET等读操作,无需修改。
内容的提问来源于stack exchange,提问作者santosh acharya
相关产品推荐
相关产品推荐

