多途径用户登陆的实现

手机号或者账号用于登陆

Django自带的用户认证后端默认是使用用户名实现用户认证的

用户认证后端位置:django.contrib.auth.backends.ModelBackend

class ModelBackend(object):
    """
    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)
        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 non-existing user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user
user = UserModel._default_manager.get_by_natural_key(username)

这一句可以简单理解为:

user = User.objects.get(username=username)

视图views.py

from django.contrib.auth import login, authenticate
from users.models import User


class LoginView(View):
    """用户登陆"""

    def get(self, request):
        """提供用户登陆页面"""
        return render(request, 'login.html')

    def post(self, request):
        """实现用户登陆逻辑"""
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        # 校验参数
        if not all([username, password]):
            return http.HttpResponseForbidden('缺少必传参数')

        # 校验用户名
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输入正确的用户名或手机号')

        # 检验密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码最少8位,最长20位')
        # 认证用户:使用账号查询用户是否存在,如果用户存在,再检验密码是否正确
        # user = User.objects.get(username=username)
        # user.check_password()
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '账号或密码错误'})
        # 状态保持
        login(request, user)
        if remembered != 'on':
            # 没有记住登陆: 状态保持在浏览器会话结束后就销毁
            request.session.set_expiry(0)   # 单位是秒
        else:
            # 记住登陆:状态保持周期为两周(默认是两周)
            request.session.set_expiry(3600)

        # 响应结果: 重定向到首页
        return redirect(reverse('contents:index'))

由于Django自带的用户认证后端默认是使用用户名实现用户认证的,如果要使用手机号做认证,需要重新定义authenticate方法。

新建文件utils.py

# 自定义用户认证的后端:实现多账号登陆
from django.contrib.auth.backends import ModelBackend
import re

from users.models import User


def get_user_by_account(account):
    """
    通过账号获取用户
    :param account: 用户名或者手机号
    :return: user
    """
    try:
        if re.match(r'^1[3-9]\d{9}$', account):
            # username == 手机号
            user = User.objects.get(mobile=account)
        else:
            # username == 用户名
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileBackend(ModelBackend):
    """自定义用户认证后端"""

    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        重写用户认证的方法
        :param request:
        :param username: 用户名或手机号
        :param password: 密码明文
        :param kwargs: 额外参数
        :return: user
        """
        # 查询用户
        user = get_user_by_account(username)
        # 如果可以查询到用户,还需要校验密码是否正确
        if user and user.check_password(password):
        # 返回user
            return user
        else:
            return None

并且在项目配置文件中指定新的AUTHENTICATION_BACKENDS

# 指定自定义用户认证的后端
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileBackend']

下面分析流程:

views.py的53行打断点

utils.py的14行打断点

后端接收到用户名和明文密码

放通断点

发现调用的是utils.py中自定义的authenticate方法

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WUYANGEZRA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值