Django 如何隐藏request.user中的密码字段
问题描述
我目前正在学习django,并且我有一个关于request.user的问题。 我已经创建了一个自定义的用户模型,并且使用了django的内置认证功能。 当我使用登录功能时,一切正常。当我打印request.user时,它返回当前用户。当我打印request.user.password时,它返回用户的哈希密码。 我知道在任何形式下都不安全地暴露用户的密码。 所以我的问题是如何从request.user中排除密码字段。 我尝试编写了一个序列化器,但没有成功。
用户模型如下
from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser, BaseUserManager
from post.models import Post
class UserManager(BaseUserManager):
def create_user(self, email, username, fullName, password):
if not email:
raise ValueError("User must provide Email")
if not username:
raise ValueError("User must provide username")
if not fullName:
raise ValueError("User must provide full name")
user = self.model(
email=self.normalize_email(email), fullName=fullName, username=username
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, full_name, password=None):
"""Create user and give Superuser privilages"""
user = self.create_user(
email=email, full_name=full_name, username=username, password=password
)
user.is_active = True
user.is_staff = True
user.is_superuser = True
print("Superuser privilages activated.")
user.save(using=self._db)
return user
class User(AbstractUser):
email = models.EmailField("Email", unique=True)
username = models.TextField("Username", max_length=100, unique=True)
fullName = models.TextField("Full Name", max_length=100)
birthDate = models.DateField("Birth Date", blank=True)
gender = models.TextField(
"Gender",
max_length=6,
blank=True,
choices=[("Male", "Male"), ("Female", "Female")],
)
profilePic = models.TextField("Profile Pic", blank=True)
profileBio = models.TextField("Profile Bio", max_length=100, blank=True)
followers = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name="Followers",
blank=True,
symmetrical=False,
)
following = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name="Following",
blank=True,
symmetrical=False,
)
verified = models.BooleanField(default=False)
private = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
regToken = models.IntegerField("Registration Token", blank=True, null=True)
objects = UserManager()
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email", "fullName"]
def __str__(self):
return self.username
def followersCount(self):
if self.followers.count():
return self.followers.count()
return 0
def followingCount(self):
if self.following.count():
return self.following.count()
return 0
def posts(self):
return Post.objects.filter(author__id=self.pk)
def postCount(self):
if self.posts():
return self.posts()
return 0
登录视图
class LoginAPI(APIView):
def post(self, request):
username = request.data["username"]
password = request.data["password"]
user = authenticate(username=username, password=password)
if user is None:
return Response(
status=status.HTTP_404_NOT_FOUND, data={"message": "Wrong Crendentials"}
)
login(request, user)
return Response(
status=status.HTTP_200_OK,
data={"message": "User Login"},
)
解决方案
如果你想在返回用户数据时不包含密码字段,你可以使用一个序列化器并控制包含在响应中的字段。
下面是一个简单的示例,展示如何使用序列化器来排除密码字段:
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
exclude = ['password']
或者包含以下字段
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['name', 'phone']
然后,在你的视图中,使用UserSerializer将request.user对象序列化,然后将其作为响应发送。这样,密码就不会包含在响应中。
只要不以任何形式返回密码,就不会有任何安全风险,因为request.user对象默认检索所有用户信息,你可以通过序列化器控制要公开的内容。