Django 不同数据库中的多重身份验证

Django 不同数据库中的多重身份验证,django,django-models,django-views,Django,Django Models,Django Views,我想创建一个简单用户和管理员都可以使用的控制面板。我有两个数据库。在admin_db中,我存储管理员,在mysql_db中,我存储简单用户。admin用户在admin_db和mysql_db中具有相同的用户名,但可能有不同的密码(出于安全和其他原因) 我的想法如下: def login(db=default, username=None): #check the authentication ...... logged_in = False while not logged_in:

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

我的想法如下:

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)
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
用户登录。如果用户名存在于admin_db中,那么也可以选择以admin身份登录(可能在html中添加另一个按钮)。否则,仅显示简单的用户选项

我怎样才能做到这一点?目前我使用默认的
@login\u 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)
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

由于没有人回答,我自己找到了一个解决方案,并将其张贴在这里,供有相同问题的人使用:

首先,我的
设置中有两个数据库。py

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',
    }
}
其概念是一个数据库中的用户也可以在admins数据库中(反之亦然)。为了帮助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
我还必须将以下行添加到我的
设置.py

数据库\u路由器=['ROUTERS.LoginRouter']

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

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)
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
然后,我将以下内容添加到我的
设置.py
中(请记住优先级问题!当django在后端成功时,它将不再继续。稍后我将提到我如何签入这两个数据库):

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

from login.models import Users as dov
from django.shortcuts import render_to_response, RequestContext
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.db import models
from django.contrib.auth.decorators import login_required


def login_user(request):
    state = "Please log in below..."
    username, password = '', ''
    if request.POST:
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                state = "You're successfully logged in!"
            else:
                state = "Your account is not active, please contact the site admin."
        else:
            state = "Your username and/or password were incorrect."

        if username != '' and 'incorrect' not in state:
            db = []
            #check to see in how many dbs' is the specific user
            try:
                dov.objects.using('mysql').get(name=username)
                db.append('mysql')
            except models.ObjectDoesNotExist:
                #we are expecting such exception if user is not in db
                pass
            except:
                #todo return error page
                return render_to_response('auth.html', {'state': 'ERROR', 'username': username},
                                          context_instance=RequestContext(request))
            try:
                User.objects.using('default').get(username=username)
                db.append('admin')
                pass
            except models.ObjectDoesNotExist:
                #we are expecting such exception if user is not in db
                pass
            except:
                #todo return error page
                return render_to_response('auth.html', {'state': 'ERROR', 'username': username},
                                          context_instance=RequestContext(request))
            return render_to_response('home.html', {'db': '{}'.format(','.join(db)), 'user': user}, context_instance=RequestContext(request))
    return render_to_response('auth.html',{'state':state, 'username': username}, context_instance=RequestContext(request))
现在您登录一个用户,并检查该用户是否存在于两个数据库中。如果两个站点上都存在用户,则可以提供管理员登录:)

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