user = authenticate(**credentials) # authenticate会自动校验用户名和密码
def authenticate(request=None, **credentials): """ If the given credentials are valid, return a User object. """ # _get_backends 是Django的配置文件中的AUTHENTICATION_BACKENDS 列表里面定义的认证方式 # 如果你自己项目的配置文件中配置了AUTHENTICATION_BACKENDS就会去你自己的配置文件中找 for backend, backend_path in _get_backends(return_tuples=True): backend_signature = inspect.signature(backend.authenticate) try: backend_signature.bind(request, **credentials) except TypeError: continue try: # 每循环一个backend 都会去调用authenticate方法 # 如果你自己重写了authenticate方法 就会走你自己写的 user = backend.authenticate(request, **credentials) except PermissionDenied: break if user is None: continue user.backend = backend_path return user
# 会从Django的配置文件中找 # from django.conf import global_settings AUTH_USER_MODEL = 'auth.User' AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']
from django.contrib.auth.backends import ModelBackend # 源码如下 class ModelBackend(BaseBackend): """ Authenticates against settings.AUTH_USER_MODEL. """ def authenticate(self, request, username=None, password=None, **kwargs): if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) if username is None or password is None: return try: # 通过自然键(USERNAME_FIELD)获取 user 对象 user = UserModel._default_manager.get_by_natural_key(username) except UserModel.DoesNotExist: UserModel().set_password(password) else: # 检查密码和是否是活跃用户,然后返回一个 user 对象,否则什么也不返回 就是 None if user.check_password(password) and self.user_can_authenticate(user): return user
因为Django自带的authenticate只能帮你验证用户名和密码,当你需要验证使用如手机号登录、邮箱登录、验证码登录等时,需要自己重写authenticate方法,自定义认证方式
from django.contrib.auth.backends import ModelBackend # 继承ModelBackend重写里面的authenticate方法 自定义认证方式 class LoginBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): user = UserInfo.objects.get(Q(username=username) | Q(phone=username) | Q(email=username)) if user is not None and user.check_password(password): return user
AUTHENTICATION_BACKENDS = [ 'app01.backends.LoginBackend' ] # 配置完之后再走校验的话就会先从你自己写的这个类里面去执行authenticate方法 # 会用你自己的校验方式