不同数据库中的多重认证

时间:2014-12-13 20:06:30

标签: django django-models django-views

我想创建一个简单用户和管理员都可以使用的控制面板。我有两个数据库。在admin_db中我存储管理员,在mysql_db中我有简单的用户。 admin的用户在admin_db和mysql_db中具有相同的用户名,但可能是不同的pass(出于安全性和其他原因)。

我的概念如下:

用户登录。如果admin_db中存在用户名,则也可以选择以admin身份登录(可能在html中添加另一个按钮)。否则只显示简单的用户选项。

我怎样才能做到这一点?目前我使用默认的@login_required,但它只检查一个数据库,我不能在数据库之间切换.. 我该怎么做以下的事情:

def login(db=default, username=None):
    #check the authentication

......

logged_in = False
while not logged_in:
    if logged_in_mysql:
        if username in admin_db:
            show button 'login_as_admin'
        else:
            continue as normal
    else:
        login(mysql_db)

.....

if user_clicks_login_as_admin:
    login(admin_db, god)

1 个答案:

答案 0 :(得分:2)

由于没有人回答,我自己找到了一个解决方案,并将其发布给任何有同样问题的人:

首先,我的settings.py中有2个数据库:

settings.py

DATABASES = {
    'default': {
        'NAME': 'myadmin',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'root',
        'PASSWORD': 'abc123',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    },
    'mysql': {
        'NAME': 'mydb',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'root',
        'PASSWORD': 'abc123',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

概念是一个数据库中的用户也可以在管理员数据库中(反之亦然)。为了帮助django同时玩两个数据库,我必须创建一个路由器,它将django指向我的登录应用程序的正确数据库。我在项目根文件夹中创建了routers.py

routers.py

class LoginRouter(object):
    """
        Router for routing login operations to mysql db
    """
    def db_for_read(self, model, **hints):
        """
            Point all operations on login models to mysql
        """
        if model._meta.app_label == 'login':
            return 'mysql'
        return 'default'

    def db_for_write(self, model, **hints):
        """
            Point all operations on login models to 'mysql'
        """
        if model._meta.app_label == 'login':
            return 'mysql'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        """
            Allow any relation if a both models in login app
        """
        if obj1._meta.app_label == 'login' and obj2._meta.app_label == 'login':
            return True
        # Allow if neither is login app
        elif 'mysql' not in [obj1._meta.app_label, obj2._meta.app_label]:
            return True
        return False

    def allow_syncdb(self, db, model):
        if db == 'mysql' or model._meta.app_label == "login":
            return False # we're not using syncdb on our legacy database
        else: # but all other models/databases are fine
            return True

我还必须将以下行添加到settings.py

DATABASE_ROUTERS = ['routers.LoginRouter']

现在,如果您拥有与经典django用户身份验证不同的身份验证,则必须创建身份验证后端。我不得不这样做,因为我的另一个数据库包含一个名为name的字段,它是身份验证的“用户名”。请注意,在我的模型中我有很多表,这就是我调用dovecot.Users的原因(我需要这里的Users表)所以再次在我的根文件夹中我创建了一个backends.py并添加了以下内容:

backends.py

#my custom model from my outer db
from login import models as dovecot
class EmailAuthBackend(object):
    """
    Email Authentication Backend

    Allows a user to sign in using an email/password pair rather than
    a username/password pair.
    """
    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = dovecot.Users.objects.get(name=username)
            if self.check_password(password, user):
                return user
        except dovecot.Users.DoesNotExist:
            return None

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        try:
            return dovecot.Users.objects.get(pk=user_id)
        except dovecot.Users.DoesNotExist:
            return None

然后我添加到我的settings.py以下(记住优先级很重要!当django在后端成功时,它将不再继续。我稍后会提到我如何检查两个dbs):

settings.py

AUTHENTICATION_BACKENDS = ('backends.EmailAuthBackend', 'django.contrib.auth.backends.ModelBackend')

所以现在我创建了一个应用程序,其中django可以检查两个数据库以查看用户是否存在并对其进行身份验证..但我还想查看mail_db中的用户是否也具有管理员权限..所以在我的{ {1}}在我的登录应用程序中,我创建了一个login_user:

views.py

现在您登录用户,同时检查两个dbs中是否存在该用户。如果两者都存在用户,则可以提供管理员登录:)

希望能帮助有类似问题的人。我在互联网上搜索了一段时间,但找不到完整的解决方案,所以我决定把它放在这里供将来参考。我希望我没有忘记任何事情或犯过任何错误

相关问题