Django两个用户授权表

2024-07-04 06:09:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须用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
]
...

新的应用程序应该能够同时登录LegacyUserUser。授权后LegacyUser.id应该用作用户标识声明。你知道吗

这意味着如果我有一个像:

{
    "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.idUser.legacy_user.id的值应该在请求中可见。你知道吗

除此之外,email字段在LegacyUserUser中必须是唯一的

这是否可能有两种用户授权模型?AUTH_USER_MODEL只能让我有一个这样的模型

AUTH_USER_MODEL = 'api.LegacyUser'

我想到的解决方案(归档向后兼容的应用程序)是将当前密码和电子邮件从LegacyUser复制到新的User模型,并将它们标记为最高权限。你知道吗

同步新系统和旧系统的密码也是必须的,这样我就可以使用一些存储过程,在数据库的更新中更改两处的密码?对我来说,它闻起来很难闻,也许有其他方法可以做到这一点,而不同步这些密码或只是使用两个表进行授权?你知道吗

Edit: To solve this issue I have created MySQL view with unified user data needed only for authorization like:

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;

So synchronization of passwords will be done automatically as view will be updated


Tags: 用户模型idtrue应用程序fieldmodelsemail
2条回答

你想看看[ahttps://docs.djangoproject.com/en/2.2/topics/auth/customizing/。你可以有许多不同的方式来验证你想要的。会话记录中存储的部分信息是成功使用了哪个身份验证后端。这有点牵扯,但他们给你所有必要的控制做几乎任何你喜欢的。你知道吗

几年前,我在一个系统上使用了它,其中主要用户/密码信息来自外部订阅管理服务器。如果user/pass在普通的用户身份验证系统上不起作用,那么我检查了另一个系统。如果成功的话,我会动态地创建一个新用户。你知道吗

您需要一个标志来区分旧用户和新用户的身份验证。 让我集中讨论基于会话的身份验证。你知道吗

AUTHENTICATION_BACKENDS = [
'common.auth.backends.CustomUserBackend'

]

从中间件中删除它django.contrib.auth.middleware.AuthenticationMiddleware,并放置CustomAuthenticationMiddleware。你知道吗

MIDDLEWARE = [
   ...
    'Your CustomAuthenticationMiddleware',
   ....
]

CustomAuthenticationMiddleware,根据session变量附加用户。你知道吗

为类CustomUserBackend实现这些方法。请阅读Auth

def get_user(self, user_id):
    # read is_legacy_user from session
    # Try to get user based on session is_legacy_user
    # Note that this method is called in CustomAuthenticationMiddleware middleware. 
    # and you have to read from 2 separate table. Session is your friend to differentiate which table we need to fetch.
def authenticate(self, request, email, password, is_legacy_user):
    if is_legacy_user:
       #write the logic for legacy user.
    else:
       #write the logic for new user.

从视图调用authenticate函数(from django.contrib.auth import 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

我希望这就是你将如何解决基于会话的身份验证问题。如果这起作用;将转向基于令牌的。你知道吗

相关问题 更多 >

    热门问题