Django跨越多个django站点的一个用户

时间:2015-11-19 07:20:58

标签: python django

我有一个案例,我有三个站点A,B,C。 A更多是管理站点,B和C是面向消费者的应用程序。他们每个人都有自己独立的数据库。我现在想做的事情如下:

我希望所有三个A,B,C以这样的方式连接:当新用户在B注册并且注册成功时,同一个用户应该能够登录到A或C.如果有的话他们反映在A和C上的用户详细信息也发生了变化。

到目前为止,我认为解决方案是:

当用户在B注册时,我可以使用相同的凭据在A和C上复制用户,因此这将允许用户登录到三个站点中的任何一个。 我也在考虑有一个存储django auth模型的中央数据库的想法,但在这种情况下我不确定验证是如何工作的。

我需要建议如何做到这一点。此外,这是否有资格被称为SSO?

如果有人发现问题具有误导性或含糊不清或不恰当,请在提示之前提及原因

1 个答案:

答案 0 :(得分:2)

您的问题有两种解决方案:

  1. 使用路由到多个数据库。 Django支持不同模型的不同数据库(关于@ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/的更多信息)。因此,您可以将身份验证模型的所有查询路由到身份验证数据库。 Django文档已经提供了这样的配置@ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#an-example。我没有测试过这种配置,但这会产生能够将外键用于您的用户模型的问题(因为它将存储在不同的数据库中)。要解决此问题,您可以在所有项目中使用UserProxy模型(或类似名称),只保留用户的用户名,以便您能够从模型创建外键关系UserProxy。需要检索的任何用户数据都将由User转发到正确的UserProxy对象。

  2. 使用django身份验证。 Django可以配置为使用许多不同的身份验证方法(请查看docs @ https://docs.djangoproject.com/en/1.8/topics/auth/customizing/)。对于站点B和C,您可以配置使用管理站点(A)的数据库登录的身份验证后端。我成功地使用了这种方法 - 在这里你可以做到这一点:

  3.   class RegUsrBackend(django.contrib.auth.backends.ModelBackend):
        def authenticate(self, username=None, password=None):
    
            try:
                conn = django.db.connections['users']
                cursor = conn.cursor()
    
                cursor.execute("select pn.password, pn.username, au.first_name, au.last_name from auth_user au where au.username = %s ", [username])
                row = cursor.fetchone()
                if row and check_password(password, row[0]):
                    user, created = get_user_model().objects.get_or_create(username = row[1] )
                    if user.first_name != row[2] or user.last_name != row[3] :
                        user.first_name = row[2]
                        user.last_name = row[3]
                        user.set_unusable_password()
                        user.save()
                    return user
            except:
                return None
    
    

    正如您所看到的,此处我还配置了一个不同的用户数据库(名为users),我向此数据库发出一个原始查询,以便为用户提供传递的用户名及其密码哈希值。之后,我检查用户是否存在并且密码是否正确(使用check_password),如果一切都检查,我使用get_or_create来检索或创建本地实例(即应用程序数据库中的用户实例) )该用户。最后,在返回用户之前,我检查是否有他的名字或名字更改为管理应用程序并在本地更新它们。

    最后,您需要将此后端放在使用它的应用程序的AUTHENTICATION_BACKENDS设置中。

    使用此方法,您不必使用任何UserProxy来支持外键(因为将存在本地用户模型)模型,但我觉得这是一种比第一种模式更为hackish的方法。此外,如果在管理数据库中更改了用户的详细信息,则其他人的详细信息将在他登录时更新。此外,您可以将后端更改为更具异国情调的内容,例如,而不是查询您可以创建的数据库管理后端中的REST API,并使用它来登录其他应用程序。

    最后,为了回答您关于SSO的问题,我上面描述的不是SSO。 SSO意味着当用户登录到站点时,由于在所有这些站点中保留并共享单个会话密钥,因此他不必再次登录到其他站点。 SSO的常见解决方案是使用CAS(http://jasig.github.io/cas/4.1.x/index.html)但是我没有很好的使用经验(并且您需要另一个,基于java的服务器托管CAS)。