Python Django用于用户授权的两个表
我必须用PHP应用程序实现一个向后兼容的Django服务器。旧版应用程序使用LegacyUser模型进行授权,或多或少类似于:Python Django用于用户授权的两个表,python,django,django-rest-framework,django-authentication,backwards-compatibility,Python,Django,Django Rest Framework,Django Authentication,Backwards Compatibility,我必须用PHP应用程序实现一个向后兼容的Django服务器。旧版应用程序使用LegacyUser模型进行授权,或多或少类似于: class LegacyUser(models.Model): id = models.BigAutoField(primary_key=True) email = models.CharField(max_length=255, unique=True) password = models.CharField(max_length=120, b
class LegacyUser(models.Model):
id = models.BigAutoField(primary_key=True)
email = models.CharField(max_length=255, unique=True)
password = models.CharField(max_length=120, blank=True, null=True)
...
other_data_fields
...
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
EMAIL_FIELD = 'email'
在一个新系统中,我不必添加LegacyUser的新记录,但我可以
目前,遗留系统不允许为每个组创建多个用户。实际上,LegacyUser应该被视为一个组,但我是作为一个用户实现的
现在,我必须为每个LegacyUser实现多个用户,因此我添加了适当的Django用户进行授权,如:
class User(AbstractUser):
username = None
email = models.EmailField(unique=True)
legacy_user = models.ForeignKey(LegacyUser, on_delete=models.DO_NOTHING)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['publisher']
class Meta:
managed = True
db_table = 'user'
在base.py设置中:
...
AUTH_USER_MODEL = 'api.LegacyUser'
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'id',
}
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend', #Supports User
'common.auth.backends.LegacyBackend' #Supports LegacyUser
]
...
新应用程序应允许登录LegacyUser和User。授权后,应将LegacyUser.id用作用户\u id\u声明
这意味着如果我有一个LegacyUser,比如:
{
"id": 1,
"email": admin@domain.com,
"password": "hashed_password",
...
}
和两个用户,例如
{
"id": 1,
"email": user1@domain.com,
"password": "hashed_password",
"legacy_user_id": 1,
...
}
LegacyUser.id或User.legacy_User.id的值应在请求中可见
此外,在LegacyUser和User中,电子邮件字段必须是唯一的
这是否可能有两种用户授权模型?AUTH_USER_模型只允许我拥有一个这样的模型
AUTH_USER_MODEL = 'api.LegacyUser'
我想到的归档向后兼容应用程序的解决方案是将当前密码和电子邮件从LegacyUser复制到新型号的用户,并将其标记为最高权限
为新系统和旧系统同步密码也是必须的,这样我就可以使用一些存储过程来更改数据库更新中两个位置的密码?对我来说,它闻起来很难闻,也许有其他方法可以做到这一点,而无需同步这些密码或仅使用两个表进行授权
编辑:为了解决这个问题,我创建了MySQL视图,其中包含了授权所需的统一用户数据,如:
CREATE OR REPLACE VIEW unified_user AS
SELECT email as email, password as password, is_active as is_active, last_login as last_login
FROM user
UNION ALL
SELECT email as email, password as password, 1 as is_active, null as last_login
FROM legacy_user;
因此,随着视图的更新,密码的同步将自动完成
您想看一下[a。您可以根据自己的意愿使用多种不同的身份验证方法。会话记录中存储的部分信息是成功使用了哪个身份验证后端。这稍微有些牵扯,但它们为您提供了所有必要的控制,让您可以做任何您喜欢的事情
几年前,我在一个系统上使用了此功能,其中主要用户/密码信息来自外部订阅管理服务器。如果用户/密码在正常的用户身份验证系统上不起作用,我会检查另一个系统。如果成功,我会动态创建一个新用户。您需要一个标志来区分旧用户的身份验证用户和新用户。 让我集中讨论基于会话的身份验证
AUTHENTICATION_BACKENDS = [
'common.auth.backends.CustomUserBackend'
]
从中间件中删除它django.contrib.auth.middleware.AuthenticationMiddleware,并放置CustomAuthenticationMiddleware
MIDDLEWARE = [
...
'Your CustomAuthenticationMiddleware',
....
]
在CustomAuthenticationMiddleware,根据会话变量连接用户
为CustomUserBackend类实现这些方法。请阅读
从视图调用来自django.contrib.auth的authenticate函数导入authenticate
对于遗留用户
user = authenticate(email, password, is_legacy_user=True)
# Store the user ID in session as well as is_legacy_user value
对于新用户
authenticate(email, password, is_legacy_user=False)
# Store the user ID in session as well as is_legacy_user value
我希望这就是解决基于会话的身份验证问题的方法。如果这样做有效;将移动到基于令牌的模式。如果我们将所有旧用户迁移到新用户模式并提供大多数特权,会出现什么问题?同步密码的原因是什么??请详细说明。问题是它必须与旧表向后兼容。假设用户使用LegacyUser表更改旧系统上的密码,则新系统和旧系统的密码将被取消同步。我想避免硬迁移。我最好慢慢迁移到新系统,保留旧系统的功能。希望我能部分解决您的问题。PHP和Django会通过RESTAPI进行通信吗?从PHP到django的请求是用于旧用户身份验证的。正当LegacyUser.id或User.legacy_User.id的值应在请求中可见。您发布的3个json有效负载是请求有效负载。正当r u使用Django REST框架?旧系统和新系统都提供与前端应用程序的REST API通信。新系统应提供系统的旧功能并添加新功能。我正在使用Django REST框架。此外,我还想为Swagger aka和端点安全提供基于会话的授权。旧系统和新系统之间的通信只能在数据库上完成,它们之间没有HTTP调用新系统必须自行实现授权
user = authenticate(email, password, is_legacy_user=True)
# Store the user ID in session as well as is_legacy_user value
authenticate(email, password, is_legacy_user=False)
# Store the user ID in session as well as is_legacy_user value