Django本身的用户管理模块是很强大的,可以满足大多种情况,但是有时候我们要对接第三方登录认证系统,就需要自己实现登录认证,幸好Django为我们提供了重新登录认证的接口,可以很好的将第三方登录方式集成到Django认证系统中。
Django默认的认证方式在settings中的AUTHENTICATION_BACKENDS中定义,使用django.contrib.auth.backends.ModelBackend模块进行认证,如果我们要重新,自定义类继承此类即可,然后在settings.py文件中显示的声明AUTHENTICATION_BACKENDS就能修改我们的认证方式。
# 设置邮箱和用户名均可登录
AUTHENTICATION_BACKENDS = (
'users.views.CustomBackend',
)
另外Django2.1本身提供的认证方式也有一点小问题,就是当我们的账号没有激活时,使用authenticate方法返回的一直是None,我们经常会使用下面的方式:
# 成功返回user对象,失败返回null
user = authenticate(request, username=user_name, password=pass_word)
# 如果不是null说明验证成功
if user is not None:
# 只有当用户激活时才给登录
if user.is_active:
先认证用户名和密码,然后再判断用户是否激活。但是很抱歉,在Django2.1中,这种方式行不通,为什么呢?在默认的ModelBackend类中,有以下实现代码:
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def user_can_authenticate(self, user):
"""
Reject users with is_active=False. Custom user models that don't have
that attribute are allowed.
"""
is_active = getattr(user, 'is_active', None)
return is_active or is_active is None
看一下user_can_authenticate函数,判断is_active,如果没有认证那么返回False,这样authenticate函数就不会返回user对象,而是返回一个None,我们上面的那种认证方式就不能实现了。这个时候就需要重写我们的认证类。在重写认证类的时候要注意,一般我们都是重写authenticate方法,但是在Django2.1中,这个方法多了一个参数: request
class ModelBackend:
"""
Authenticates against settings.AUTH_USER_MODEL.
"""
def authenticate(self, request, username=None, password=None, **kwargs):
......
......
之前一直是没有写request参数,也没有传入,导致认证的时候一直报错,自定义认证没有生效,而且还导致所有认证方式都不能执行。跟踪了源码才发现这个问题,在这里记录一下,以后不要在犯了!!!!
网友评论