凭证正确但无法通过Curl与Django JWT登录,附自定义用户模型代码
首先,我先从你贴出的自定义UserManager代码里发现了一个很容易踩的坑,再结合JWT认证的常见问题,一步步帮你排查:
1. 修复UserManager方法名的拼写错误
你写的方法是create_User(首字母U大写),但Django的BaseUserManager必须要求这个方法是小写的create_user——Python是大小写敏感的,框架内部会默认调用这个特定名称的方法来创建用户。如果方法名不对:
- 可能导致用户创建时密码没有被正确哈希(如果你的方法里有
set_password逻辑的话) - 后续JWT认证时,无法正确匹配到用户实例
修改方法名:
class UserManager(BaseUserManager): # 把create_User改成create_user def create_user(self, email, name, companyname=None, userphoto=None, userphotokey=None, signupvalidatestring=None, is_active=False, phone=None, jobtitle=None, isclient=False, issuitsviewer=False, issuitsadministrator=False, issuitssuperuser=False, password=None): if not email: raise ValueError('Users must have an email address') if not name: raise ValueError('Users must have a name') user = self.model(email=self.normalize_email(email), name=name) # 确保这里调用了set_password来哈希密码 if password: user.set_password(password) user.save(using=self._db) return user
2. 检查密码是否被正确哈希
如果你的create_user方法里没有调用user.set_password(password),密码会以明文存储,而JWT认证时会用哈希后的密码去比对,自然会失败。一定要确保密码被正确哈希后再保存用户。
3. 配置JWT使用Email作为认证字段
默认情况下,django-rest-framework-simplejwt会用username字段做认证,但你的自定义用户模型用的是email作为唯一标识。需要在settings.py里添加配置:
SIMPLE_JWT = { 'USER_ID_FIELD': 'email', 'USER_ID_CLAIM': 'user_email', # 如果你的登录接口需要用email和password,还要确保Serializer正确 }
或者在自定义的JWT登录Serializer里指定认证字段:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer class CustomTokenObtainPairSerializer(TokenObtainPairSerializer): @classmethod def get_token(cls, user): token = super().get_token(user) # 可以添加自定义字段 token['email'] = user.email return token def validate(self, attrs): # 用email替换username做认证 attrs['username'] = attrs['email'] return super().validate(attrs)
4. 检查Curl请求的格式是否正确
确保你的Curl请求是POST方法,并且用application/json格式传递参数,字段名要和JWT认证的字段匹配:
curl -X POST \ http://localhost:8000/api/token/ \ -H "Content-Type: application/json" \ -d '{"email": "your-test-email@example.com", "password": "your-test-password"}'
如果你的登录接口用的是username字段(即使实际是email),就把email换成username。
5. 确认用户的is_active状态
你的create_user方法默认is_active=False,而JWT认证默认要求用户是活跃状态。如果创建用户后没有手动激活(设置is_active=True),即使凭证正确也会登录失败。可以在创建用户时默认设为True,或者在用户验证后激活:
# 修改create_user里的默认参数 def create_user(self, ..., is_active=True, ...):
6. 检查自定义用户模型的全局配置
确保在settings.py里指定了你的自定义用户模型,否则Django会用默认的auth.User,导致你的自定义用户无法被认证:
AUTH_USER_MODEL = 'your_app_name.YourUserModelName'
按照上面的步骤排查后,应该能解决凭证正确但登录失败的问题。
内容的提问来源于stack exchange,提问作者user9487981

