我想在我的项目中实现临时用户。原因是人们应该能够通过Facebook Oauth或Facebook Account Kit在我的应用程序中进行身份验证。
我有2个决定,但每个决定都不理想。
1)。创建用户和临时用户模型。第一个将具有有关常规用户+唯一数据库字段的所有信息。该临时用户将只有phone_number
或facebook_id
。临时用户将在auth/
端点上创建,并且响应将具有auth_token
,以便以后可以在所有必需字段中进行注册。
问题是::如何确定用户是临时用户,而他的auth_token
仅对registration/
端点合法?
2)创建具有两种类型的基本用户模型:regular
或temporary
。该模型将仅具有常规字段。此外,还有与用户具有OneToOne关系的不同模型。只有类型为regular
的用户才能拥有具有OneToOne关系的实例。
问题是:用户模型应具有USERNAME_FIELD
,REQUIRED_FIELDS
才能通过管理面板登录+不同类型的用户应具有不同的管理员。
已更新
class User(AbstractBaseUser, TimeStampedModel, PermissionsMixin):
is_regular = models.BooleanField(
default=False
)
id = models.CharField(
max_length=11,
primary_key=True,
default=custom_uuid,
editable=False
)
phone_number = PhoneNumberField(
null=True
)
facebook_id = models.CharField(
max_length=255,
null=True
)
objects = UserManager()
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELDS = []
答案 0 :(得分:1)
通过讨论,有很多方法可以解决此问题。但是将两种不同的模型用于身份验证是一个坏主意。因为Django Auth的设计是假设一个用户模型。
这就是我应该采取的方式:
facebook_id
而不是使用email
。创建密码时,我会使用唯一的UUID。其他绝对必要的信息,我将使用一个单独的模型来存储它们。例如:
class Profile(models.Model):
...
phone_number = models.CharField(max_length=30)
user = models.OneToOneField(settings.AUTH_USER_MODEL)
并登录后检查用户是否具有个人资料:
if not hasattr(user, 'profile'):
# redirect to more information page
对于其他访问管理网站的权限,应通过常规注册或社会注册来限制创建。对于这些用户,这些字段(is_staff
,is_superuser
等默认情况下应为False。对于创建管理员用户,您可以使用createsuperuser命令。对于工作人员用户,您以后可以分配一个普通用户用户可以通过在管理员网站或is_staff
上放置True
标志Django Shell
来进行人员配备。
您可以使用自定义后端来验证Facebook用户:
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
class CustomModelbackend(ModelBackend):
def authenticate(self, phone_no=None, password=None, facebook_id=None, **kwargs):
# Override
UserModel = User
try:
user = UserModel.objects.get(Q(phone_no=phone_no) | Q(facebook_id=facebook_id))
if password and user.check_password(password):
return user
elif facebook_id:
return user
except Exception as e:
# log exception
并将其添加到settings.py
中的AUTHENTICATION_BACKENDS:
AUTHENTICATION_BACKENDS = ['path.to.custom_backend.CustomBackend']
并调用如下所示的authenticate方法:
authenticate(phone_no=phone_number, password=password) # for normal auth
authenticate(facebook_id=facebook_id) # for social auth
但是您不能使您的phone_no
唯一,因为有可能phone_no为空,无法用于社交登录,但是您可以将其放在USERNAME_FIELD
中。因此,当您运行django开发人员服务器时,会看到警告( runserver 命令)
您可以尝试这样:
NORMAL_USER = "N"
OAUTH_USER = "O"
AT_USER = "A"
USER_TYPES=(
(NORMAL_USER, 'Normal User'),
(OAUTH_USER, 'Oauth User'),
(AT_USER, 'Account Toolkit User')
)
class User(...):
username = models.CharField(max_length=255, default=uuid.uuid4, unique=True) # it might be unnecessary
account_type = models.CharField(max_length=2, choices = USER_TYPES, default=NORMAL_USER)
identifier = models.CharField(max_length=255)
...
class Meta:
unique_togather = ('account_type', 'identifier',)
# for Oauth Creation
User.objects.create(account_type=OAUTH_USER, identifier=facebook_id) # or email
# for Toolkit Creation
User.objects.create(account_type=AT_USER, identifier=phone_number)
# For normal User
User.objects.create(identifier=username, username=username)
#backend, and does not need to use ModelBackend, it will work with adminsite
class CustomBackend(...):
def authenticate(self, **kwargs):
try:
identifier= kwargs.get('username')
password=kwargs.get('password')
account_type=kwargs.get('account_type', NORMAL_USER)
user = User.objects.get(identifier=identifier, account_type=account_type)
if user.check_password(password):
return user
except Exception:
# log exception
# authentication
from django.contrib.auth import authenticate
user = authenticate(username=identifier, password=password, account_type=OAUTH_USER)