我有一个用Django编写的应用程序,我需要扩展它并将其他解决方案作为“应用程序”包含在此应用程序中。
例如,要集成的我的应用程序名为“my_new_app”,但主要应用程序已经编写了后端身份验证,我不能使用它。
我有一个MySQL数据库供查询,而主要应用程序大多使用Cassandra和Redis。
是否有任何方法可以为新应用程序“my_new_app”使用单独的身份验证后端并在同一域中运行两个应用程序?
我有一个用Django编写的应用程序,我需要扩展它并将其他解决方案作为“应用程序”包含在此应用程序中。
例如,要集成的我的应用程序名为“my_new_app”,但主要应用程序已经编写了后端身份验证,我不能使用它。
我有一个MySQL数据库供查询,而主要应用程序大多使用Cassandra和Redis。
是否有任何方法可以为新应用程序“my_new_app”使用单独的身份验证后端并在同一域中运行两个应用程序?
您可以使用多个认证后端。只需在Django项目的settings.py
中设置AUTHENTICATION_BACKENDS
,列出您想要使用的后端实现即可。例如,我经常将OpenID认证与标准的Django认证结合使用,就像在我的settings.py
中这样设置:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'django_openid_auth.auth.OpenIDBackend',
)
在这个例子中,Django首先尝试使用django.contrib.auth.backends.ModelBackend
进行身份验证,这是Django的默认后端。如果失败,则继续使用下一个后端django_openid_auth.auth.OpenIDBackend
。django_openid_auth
添加到INSTALLED_APPS
中,否则Django将无法导入并将其用作后端。我之前遇到过这个问题。这是我所使用的代码。
这是在api/backend.py
中的身份验证后端。
from django.contrib.auth.models import User
class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
这是我的settings.py
文件。
AUTHENTICATION_BACKENDS = (
'api.backend.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
这段代码将使您能够在Django管理界面中使用电子邮件对默认Django用户进行身份验证。
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.Backend1',
'django_openid_auth.auth.Backend2',
)
AUTHENTICATION_BACKENDS = (
'social_core.backends.open_id.OpenIdAuth',
'social_core.backends.google.GoogleOpenId',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.google.GoogleOAuth',
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
def signup_view(request):
if request.method=='POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user=form.save()
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect('home')
对代码进行了一些安全性和重组,因为提供的解决方案并不完全符合要求。
我对之前的版本进行了修改:https://dev59.com/2GQn5IYBdhLWcg3wJ0QO#17078818,并加入了@M.Void的评论:
这是位于api/backend.py的身份验证后端。
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.core.validators import validate_email
user_model = get_user_model()
class EmailOrUsernameModelBackend(ModelBackend):
"""EmailOrUsernameModelBackend - UsernameOrEmail custom authentication backend
with email or username validation on same field
provides case insensitive validation of username and email
BEWARE - if you allow users to register two usernames in differren cases like: Alex and alex - there would be error.
still uses ModelBackend so provides permissions and is_active validation
"""
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(user_model.USERNAME_FIELD)
if username is None or password is None:
return
try:
validate_email(username)
except ValidationError as e:
kwargs = {'username__iexact': username} # remove __iexact to make it case sensitive
else:
kwargs = {'email__iexact': username} # remove __iexact to make it case sensitive
try:
user = user_model.objects.get(**kwargs)
except user_model.DoesNotExist:
return None
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
return user_model.objects.get(pk=user_id)
except user_model.DoesNotExist:
return None
当然,将其添加到您的身份验证后端中:
AUTHENTICATION_BACKENDS = (
'api.backend.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
if '@' in username:
来识别用户名是否为电子邮件是一种相当糟糕的方法。你应该至少使用模式匹配或在源代码中确定所选选项。 - vintagexavif '@' in username:
,而是像这样使用django.core.validators.validate_email
:def validateEmail(email): try: validate_email(email) return True except ValidationError: return False
- M.Void