简体   繁体   English

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

[英]Django one user across multiple django sites

I have a case where I have three sites A, B, C . 我有一个情况,我有三个站点A,B,C。 A is more of administrative site, B and C are consumer facing applications. A更多是管理站点,B和C是面向消费者的应用程序。 Each of them have their own separate databases. 他们每个人都有各自独立的数据库。 What I want to do now is as follows: 我现在想做的如下:

I want all three A, B, C to be connected in such a way that when a new user registers at B and when registration is successful, the same user should be able to login into A or C. If there is any change in users details they reflect on A and C as well. 我希望所有三个A,B,C都以这样的方式连接:当新用户在B上注册并且注册成功时,同一用户应该能够登录A或C。如果用户有任何更改,它们也会反映在A和C上。

What I thought as solution till now is: 到目前为止,我认为解决方案是:

When a user registers at B, I can replicate user on A and C with same credentials, so this would allow user to login into any of the three sites. 当用户在B处注册时,我可以使用相同的凭据在A和C上复制用户,因此这将允许用户登录这三个站点中的任何一个。 I was also pondering upon idea of having a central database to store django auth models, but I am not sure in that case how authentication would work. 我也在考虑拥有一个中央数据库来存储Django身份验证模型的想法,但是我不确定那种情况下身份验证将如何工作。

I need suggestion as to how this can be done. 我需要有关如何完成此操作的建议。 Also, does this qualify to be called as SSO? 此外,这是否有资格被称为SSO?

In case if someone finds question to be misleading or vague or inappropriate do mention as to why before downvoting 如果有人发现问题是误导性的,模糊的或不适当的,请在投票之前提及原因

There are two solutions to your problem: 您的问题有两种解决方案:

  1. Use routing to multiple databases. 使用路由到多个数据库。 Django supports different databases for different models (more info on @ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/ ). Django支持不同模型的不同数据库(有关更多信息,请参见@ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/ )。 So you could route all queries for your auth models to the authentication database. 因此,您可以将针对身份验证模型的所有查询路由到身份验证数据库。 Django documentation already provides such a configuration @ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#an-example . Django文档已经提供了这样的配置@ https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#an-example I've not tested this configuration however this will have the problem of not being able to use foreign keys to your user model (since it will be stored in a different database). 我没有测试这种配置然而,这将能够使用外键到用户模式的问题(因为它会被存储在不同的数据库)。 To resolve this, you could have a UserProxy model (or something similarly named) in all your projects that will just keep the username of the User so you'll be able to create foreign key relations from your models to the UserProxy. 要解决此问题,您可以在所有项目中都有一个UserProxy模型(或类似名称的模型),该模型将仅保留User的用户名,以便您能够创建从模型到UserProxy的外键关系。 Any user data that would need to be retrieved would be forwarded to the correct User object by the UserProxy . UserProxy将把需要检索的任何用户数据转发到正确的User对象。

  2. Use django authentication. 使用Django身份验证。 Django can be configured to use a number of different authentication methods (check the docs @ https://docs.djangoproject.com/en/1.8/topics/auth/customizing/ ). 可以将Django配置为使用多种不同的身份验证方法(请检查docs @ https://docs.djangoproject.com/en/1.8/topics/auth/customizing/ )。 For your sites B and C you can configure an authentication backend that uses the database of the administrative site (A) to login. 对于站点B和C,您可以配置使用管理站点(A)的数据库登录的身份验证后端。 I am using this method succesfully - here how you could do it: 我正在成功使用此方法-在这里您可以做到这一点:

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

As you can see, here I've also configured a different users database (named users ) and I am issuing a raw query to this database to get the user with the passed username and its password hash. 如您所见,在这里我还配置了一个不同的users数据库(名为users ),并向该数据库发出原始查询,以获取具有传递的用户名及其密码哈希的用户。 After that, I check if the user exists and has the correct password (using the check_password) and if everything checks, I use get_or_create to either retrieve or create the local instance (ie the instance of the user in the application's database) of that user. 之后,我检查用户是否存在并具有正确的密码(使用check_password),如果一切都检查了,我使用get_or_create来检索或创建该用户的本地实例(即应用程序数据库中的用户实例)。 。 Finally, before returning the user I check to see if there's a change in his first or last name to the administrative application and update them in the local one. 最后,在返回用户之前,我先检查他的名字或姓氏是否对管理应用程序有所更改,然后在本地对其进行更新。

Finally, you need to put this backend in the in the AUTHENTICATION_BACKENDS settings of the applications using it. 最后,您需要将此后端放入使用它的应用程序的AUTHENTICATION_BACKENDS设置中。

Using this method you won't have to use any UserProxy to support foreign keys (since there will exist a local User model) models but I feel that it is a more hackish method than the first one. 使用这种方法,您将不必使用任何UserProxy来支持外键(因为将存在本地User模型),但是我觉得它比第一种方法更糟糕。 Also, if the details of a user has been changed in the administrative database the details in the others will be updated when he logs in. Also you could change your backend to something even more exotic, for example instead of querying the database you could create a REST api in your administrative backend and use this to login to the other applications. 另外,如果用户的详细信息已在管理数据库中更改,则其他用户的详细信息将在他登录时更新。此外,您还可以将后端更改为更特殊的内容,例如,而不是查询您可以创建的数据库您的管理后端中的REST api,并使用它来登录其他应用程序。

Finally, to answer your question about SSO, what I've described above is not SSO. 最后,为了回答您有关SSO的问题,我上面描述的不是SSO。 SSO means that when a user logs in to a site he won't have to log in again to the others becase a single session key is kept and shared in all these sites. SSO意味着,当用户登录到一个站点时,他无需再次登录其他站点,只要在所有这些站点中保留并共享一个会话密钥即可。 A common solution for SSO is to use CAS ( http://jasig.github.io/cas/4.1.x/index.html ) however I don't have good experience with it (and you'll need to have another , java based server to host CAS). SSO的常见解决方案是使用CAS( http://jasig.github.io/cas/4.1.x/index.html ),但是我对此没有很好的经验(并且您还需要另外一个 ,基于Java的服务器来托管CAS)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM