我正在编写Django应用程序的身份验证。遵循Thinkster Django课程的代码,我实现了整个注册过程,但是我无法登录,因为在注册用户时密码没有被哈希化。
这是我的自定义用户模型和create_user
功能。
class UserManager(BaseUserManager)
def create_user(self, username, email, password=None):
if username is None:
raise TypeError('Users must have a username.')
if email is None:
raise TypeError('Users must have an email address.')
user = self.model(username=username, email=self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_superuse(self, username, email, password):
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(username, email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(db_index=True, max_length=255, unique=True)
email = models.EmailField(db_index=True, unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
正如您所看到的,我明确地调用set_password
函数,但我无法找到,为什么它没有得到正确执行?
我创建用户的Serializer
如下:
class RegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(
max_length=128,
min_length=8,
write_only=True
)
token = serializers.CharField(max_length=255, read_only=True)
class Meta:
model = User
fields = ['email', 'username', 'password', 'token']
def create(self, validated_data):
return User.objects.create_user(**validated_data)
请注意,我还尝试return User.objects.create_user(**validated_data)
而不是return get_user_model().objects.create_user(**validated_data)
,因为这是另一个问题的建议,但这也不起作用。
我也发表了我的观点,以防万一有问题,但我真的认为不是这样。
class RegistrationAPIView(APIView):
permission_classes = (AllowAny,)
renderer_classes = (UserJSONRenderer,)
serializer_class = RegistrationSerializer
def post(self, request):
user = request.data.get('user', {})
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
旁注:如果相关,我会发送Postman
的请求,我收到的所有回复似乎完全正确。但是当我浏览我的SQLite时,我发现密码没有被散列。这也导致用户无法登录,因为在登录过程中密码被散列,然后与数据库中的密码进行比较。
附注2 :当我通过命令行向python manage.py createsuperuser
注册用户时,它会获得一个哈希密码,一切正常,正如我通常所期望的那样。
答案 0 :(得分:2)
我在make_password
的上述评论中的含义是在create_user
方法中添加以下内容:
from django.contrib.auth.hashers import make_password
def create_user(self, username, email, password=None):
if username is None:
raise TypeError('Users must have a username.')
if email is None:
raise TypeError('Users must have an email address.')
user = User.objects.create(
email=email,
username=username,
password = make_password(password))
return user
答案 1 :(得分:1)
您需要在序列化程序中使用这样的set_password方法:
def create(self, validated_data):
user = User(email=validated_data['email'], username=validated_data['username'])
user.set_password(validated_data['password'])
user.save()
return user
答案 2 :(得分:0)
我认为Surajano正在做点什么。我不知道这是否能解决您的问题,但我一时间遇到了同样的问题,创建了一个没有哈希密码的超级用户。
我是如何解决的:
def create_superuser(self, email, first_name, last_name, password):
user = self.create_user(
email,
first_name,
last_name,
password=password,
)
您必须明确设置密码=密码
另外,我在你的def create_superuser中看到一个拼写错误(你将它作为def create_superuse),这可能会让你以后遇到麻烦。
无论如何我在这个和解决方案上发布了一个问题,你可以在这里查看:
我再也不知道这是否会对您有所帮助,但希望它能让您了解至少跟踪解决方案。我的例子不是使用基于令牌的身份验证 - 所以没有序列化程序 - 但我认为这很重要,因为这些可能不相关。