Django 不同数据库中的多重身份验证
我想创建一个简单用户和管理员都可以使用的控制面板。我有两个数据库。在admin_db中,我存储管理员,在mysql_db中,我存储简单用户。admin用户在admin_db和mysql_db中具有相同的用户名,但可能有不同的密码(出于安全和其他原因) 我的想法如下: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:
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))
现在您登录一个用户,并检查该用户是否存在于两个数据库中。如果两个站点上都存在用户,则可以提供管理员登录:)
希望这能帮助任何有类似问题的人。我在互联网上搜索了一段时间,没有找到一个完整的解决方案,所以我决定把这个放在这里作为将来的参考。我希望我没有忘记任何事情或犯任何错误