我有一个用 Django 编写的应用程序,我必须对其进行扩展,并在此应用程序中包含一些其他解决方案作为“应用程序”。
例如,我要集成的应用程序名为“my_new_app” 现在有一个为主应用程序编写的后端身份验证,我不能使用它。
我有一个 MySQL 数据库可供查询,主要应用程序主要使用 Cassandra 和 Redis。
有什么方法可以为新应用程序“my_new_app”使用单独的身份验证后端并在同一个域中运行?
我有一个用 Django 编写的应用程序,我必须对其进行扩展,并在此应用程序中包含一些其他解决方案作为“应用程序”。
例如,我要集成的应用程序名为“my_new_app” 现在有一个为主应用程序编写的后端身份验证,我不能使用它。
我有一个 MySQL 数据库可供查询,主要应用程序主要使用 Cassandra 和 Redis。
有什么方法可以为新应用程序“my_new_app”使用单独的身份验证后端并在同一个域中运行?
您可以有多个身份验证后端。只需设置 Django 项目的AUTHENTICATION_BACKENDS
insettings.py
以列出您要使用的后端实现。例如,我经常结合使用 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 可见的路径中。在这个例子中,我必须添加django_openid_auth
to INSTALLED_APPS
,否则 Django 将无法导入它并将其用作后端。
还阅读了相关文档,写得非常好,易于理解: https ://docs.djangoproject.com/en/dev/topics/auth/customizing/
我以前遇到过这个问题。这是我使用的代码。
这是身份验证后端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 admin 中也是如此。
使用多个后端身份验证就像馅饼一样简单。您只需要了解 Django 应用程序的工作流程。
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.Backend1',
'django_openid_auth.auth.Backend2',
)
例如,您定义了以下两个后端。Django 将首先转到第一个后端,您只需在该后端放置一些逻辑,这样,如果它与该后端无关,它将被转发到另一个后端或返回而没有任何结果。如果没有结果,django 会自动将请求从第一个后端转移到第二个后端,如果可用,第三个后端。我花了很多时间在这上面,发现它并没有那么复杂。
使用 Multiple AUTHENTICATION BACKENDS 非常简单,只需将其添加到 settings.py
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',
)
这可能会在注册页面上产生问题,因此请在您的注册视图中的 views.py 文件中添加一个登录参数,例如 login(request, user, backend='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 ://stackoverflow.com/a/17078818/14972653 加上我的补充和@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',
)