【发布时间】:2019-08-30 14:04:10
【问题描述】:
我必须用 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, blank=True, null=True)
...
other_data_fields
...
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
EMAIL_FIELD = 'email'
在新系统中,我不必添加LegacyUser 的新记录(但我可以)。
目前,旧系统不允许为每个组创建多个用户。实际上LegacyUser 应该被视为一个组,但我是作为用户实现的。
现在我必须为每个 LegacyUser 实现多个 Users,所以我添加了适当的 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 应用作 USER_ID_CLAIM。
这意味着如果我有一个 LegacyUser 喜欢:
{
"id": 1,
"email": admin@domain.com,
"password": "hashed_password",
...
}
还有两个用户,例如
{
"id": 1,
"email": user1@domain.com,
"password": "hashed_password",
"legacy_user_id": 1,
...
}
{
"id": 2,
"email": user2@domain.com,
"password": "hashed_password",
"legacy_user_id": 1,
...
}
LegacyUser.id 或 User.legacy_user.id 的值应在请求中可见。
更重要的是email 字段在LegacyUser 和User 中必须是唯一的
这可能有两个用户授权模型吗? AUTH_USER_MODEL 只能让我拥有一个这样的模型
AUTH_USER_MODEL = 'api.LegacyUser'
我想到的解决方案(存档向后兼容的应用程序)是将当前密码和电子邮件从 LegacyUser 复制到新模型 User 模型并将它们标记为最高权限。
还必须为新系统和旧系统同步密码,这样我就可以使用一些存储过程,在更新时更改数据库中两个地方的密码?对我来说,它闻起来很糟糕,也许有其他方法可以在不同步这些密码或仅使用两个表进行授权的情况下做到这一点?
编辑:为了解决这个问题,我创建了 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;因此,随着视图的更新,密码的同步将自动完成
【问题讨论】:
-
如果我们将所有旧用户迁移到新用户模型并提供大多数权限会出现什么问题?密码同步的原因是什么??请详细说明。
-
这个问题是它必须向后兼容旧表。假设用户使用 LegacyUser 表在旧系统上更改密码,那么新旧系统的密码将不同步。我想避免硬迁移。我还是慢慢迁移到新系统留下旧系统的功能会更好
-
希望我能部分解决您的问题。 PHP 和 Django 会通过 REST API 进行通信吗?从 PHP 到 django 的请求是用于旧版用户身份验证。正确的? LegacyUser.id 或 User.legacy_user.id 的值应该在请求中可见。您发布的 3 个 json 有效负载是请求有效负载。正确的?你在使用 Django REST 框架吗?
标签: python django django-rest-framework django-authentication backwards-compatibility