多个Django应用程序,共享身份验证

时间:2013-08-14 11:13:07

标签: django django-authentication

此问题的两个答案,取决于是否跨不同网站或不同子域进行共享第二个答案:Multiple Django apps, shared authentication

用户访问site1.com并登录。现在,如果他访问site2.com,那么他应该已经在该站点登录(已验证)。

site1.com和site2.com由同一服务器上的不同Django应用程序处理。

我知道网站可以共享包含身份验证表的数据库。我没有得到的是如何处理会话数据。登录到site1后,用户转到site2。在这里,他总是有request.user =“AnonymousUser:AnonymousUser”而不是user_id。

我已将其设置为:https://docs.djangoproject.com/en/dev/topics/db/multi-db/

site1的设置包含一个包含auth模型以及其他一些数据表的数据库。 site2的设置有2个数据库。一个有自己的数据表,也有user1使用的数据表。我基本上复制了类AuthRouter并设置了数据库路由器。

我想要做的不可能吗?我实际上并不了解两个站点如何共享会话数据。在Django之外我需要一些特别的东西吗?或者这应该工作?我可以在这里包含我的代码,但如果我对此的基本思考是错误的,不要混淆问题。

编辑:这是我的设置。我在localhost上尝试这个。

Site1在localhost上运行:8080

site2在localhost:8000

上运行

第2页APP:

db_router.py:

class AuthRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'auth':
            return 'the_ui'
        return None
    # same for write

    def allow_syncdb(self, db, model):
        if db == 'the_ui':
            return model._meta.app_label == 'auth'
        elif model._meta.app_label == 'auth':
            return False
        return None

class OtherRouter(object):
    def db_for_read(self, model, **hints):
        return "default"
    # same for write, relation, syncdb

settings.py:

DATABASE_ROUTERS = ['site2_app.db_router.AuthRouter', 'site2_app.db_router.OtherRouter']
SESSION_COOKIE_DOMAIN = 'http://localhost:8080'
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"

DATABASES = {
    'default': {
        # ...
    },
    'the_ui': {
        # ...
    }
}

第1页APP:

# no router
# only single database, same as the "the_ui" used in site2
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"

4 个答案:

答案 0 :(得分:14)

根据使用不同网站的初始问题,标记的答案是正确的。

以下是不同子域的答案,例如www.site.com和shop.site.com

使用问题中描述的共享数据库身份验证。然后,在两个settings.py中:

SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
SESSION_COOKIE_DOMAIN = '.site.com' #notice the period
SESSION_COOKIE_NAME = 'my_cookie'
SECRET_KEY = "" the same in both settings.py

如果您有其他不应共享此信息的子域,可能会出现一些问题。或者,也许不是,如果你给他们的饼干不同的名字??

不确定这是否适用于localhost。

答案 1 :(得分:3)

正如您所说,这两个站点可以通过共享数据库或在各自的数据库之间同步Users表来拥有相同的身份验证数据。

这将确保site1.com的任何用户自动成为site2.com的成员,反之亦然。

但您对登录site1.com的任何用户的要求应该自动登录site2.com有点棘手。你真正需要的是Single Sign On (SSO).

仅仅共享数据库(包括会话数据)无法实现的原因是因为跨域问题。

使用Django有许多SSO解决方案。看看this SO问题。虽然我从未使用它,Django-openid似乎是个不错的选择。

答案 2 :(得分:0)

您可以使用database routers指定哪个数据库应该用于auth后端。

这里我给出了一个示例路由器代码:

class UserSessionRouter(object):

    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'auth':
            return 'usersandsessions'
        elif model._meta.app_label == 'accounts':
            return 'usersandsessions'
        elif model._meta.app_label == 'sessions':
            return 'usersandsessions'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'auth':
            return 'usersandsessions'
        elif model._meta.app_label == 'accounts':
            return 'usersandsessions'
        elif model._meta.app_label == 'sessions':
            return 'usersandsessions'
        return None

然后使用数据库设置DATABASE_ROUTERSSESSION_COOKIE_DOMAIN指定路由器,如下所示

DATABASE_ROUTERS = ['site2.routers.UserSessionRouter']
SESSION_COOKIE_DOMAIN = 'site1.com'

答案 3 :(得分:-1)

正如Sudipta所说,openid是实现SSO的一种方式。

另一种方法是直接使用SAML(有一些工具用于此),或者像Stormpath(https://stormpath.com)这样的托管服务为你做SSO的东西,并直接支持Django的auth系统: https://github.com/stormpath/stormpath-django

我在Stormpath工作,非常有偏见,但我认为我会因为关于SSO + Django解决方案存在很多混淆而引起注意。