django自定义验证方法

1.一般django默认使用的验证是用户加密码,如果在用户数据表中含有邮箱字段,并且想要通过邮箱验证用户登录该怎么实现呢。方法如下。

一.自定义验证backend

from django.contrib.auth.models import AbstractUser
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
class CustomBackends(ModelBackend):
    #自定义验证方法,通过邮箱或者用户名登陆
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user=UserProfile.objects.get(Q(username=username) | Q(email=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None

自定义的验证backend需要集成django自带的ModelBackend,并且重写authenticate方法,然后再settings配置文件中加入下面这句配置

AUTHENTICATION_BACKENDS=(
    'users.models.CustomBackends',
)

其中users是我的一个django中的app,我将CustomBackends这个自定义backend放在了其中的models文件中。

二.view方法和前段代码编写

view函数

from django.shortcuts import render
from django.contrib.auth import authenticate,login
from django.views.generic import View
class LoginView(View):
    def get(self,request):
        return render(request, "login.html", {})
    def post(self,request):
        login_form=LoginForm(request.POST)
        if login_form.is_valid():
            user_name = request.POST.get("username", "")
            pass_word = request.POST.get("password", "")
            user = authenticate(username=user_name, password=pass_word)
            if user is not None:
                login(request, user)
                return render(request, "index.html")
            else:
                return render(request, "login.html", {"msg": "用户名,邮箱或密码错误"})
        else:
            return render(request, "login.html", {"login_form":login_form})

前段表单代码

<form action="/login/" method="post" autocomplete="off">
                    <input type='hidden' name='csrfmiddlewaretoken' value='mymQDzHWl2REXIfPMg2mJaLqDfaS1sD5' />
                    <div class="form-group marb20 {% if login_form.errors.username %}errorput{% endif %}" >
                        <label>&nbsp;&nbsp;</label>
                        <input name="username" id="account_l" type="text" placeholder="手机号/邮箱" />
                    </div>
                    <div class="form-group marb8 {% if login_form.errors.password %}errorput{% endif %}">
                        <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
                        <input name="password" id="password_l" type="password" placeholder="请输入您的密码" />
                    </div>
                    <div class="error btns login-form-tips" id="jsLoginTips">{% for key,error in login_form.errors.items %}{{error}}{% endfor %}{{msg}}</div>
                     <div class="auto-box marb38">

                        <a class="fr" href="forgetpwd.html">忘记密码?</a>
                     </div>
                     <input class="btn btn-green" id="jsLoginBtn" type="submit" value="立即登录 > " />
                <input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy' />
                {% csrf_token %}
                </form>

那么我们底层是到底如何实现验证的呢,我们可以结合实际代码来讲解,由于本人不懂前端,只能略作分析。首先关注 <input name="username" id="account_l" type="text" placeholder="手机号/邮箱" /><input name="password" id="password_l" type="password" placeholder="请输入您的密码" /> 这两句,当我们点击submit登录按钮后前端会向后端发起一个post请求,我们可以通过debug模式来查看该post请求中的具体内容

在这里插入图片描述

在这里插入图片描述

我们看到在request中有一个POST属性,是一个字典类型数据。
其中有username和password键值对,所以我们可以知道前端向后端发起的POST请求的内容是根据INPUT 标签中的name属性来生成的,所以我们通过request.POST.get(“username”,"")来获取用户名,所以我们如果在前端传入的是用户的邮箱那么我们就能得到如下图。
在这里插入图片描述

在这里插入图片描述
可以看到我们POST中的键还是username,但是内容已经是邮箱,所以我们可以基于此点来修改验证方式,在看看我们开头出所写到的自定义backend

from django.contrib.auth.models import AbstractUser
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
class CustomBackends(ModelBackend):
    #自定义验证方法,通过邮箱或者用户名登陆
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user=UserProfile.objects.get(Q(username=username) | Q(email=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None

我们可以看到在CoustBackends中和LoginView中都有一个authenicate函数,那么这两个authenticate之间有什么关联呢。我们可以先看看LoginView中的authenticate源码

def authenticate(**credentials):
    """
    If the given credentials are valid, return a User object.
    """
    for backend, backend_path in _get_backends(return_tuples=True):
        try:
            inspect.getcallargs(backend.authenticate, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue

        try:
            user = backend.authenticate(**credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            return None
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__,
            credentials=_clean_credentials(credentials))

首先我们可以看到其实在authenticate方法内部还调用了backend.authenticate方法,那这个backend是什么呢。我们可以看看_get_backends方法到底做了什么

def _get_backends(return_tuples=False):
    backends = []
    for backend_path in settings.AUTHENTICATION_BACKENDS:
        backend = load_backend(backend_path)
        backends.append((backend, backend_path) if return_tuples else backend)
            'No authentication backends have been defined. Does '
            'AUTHENTICATION_BACKENDS contain anything?'
        )
    return backends

看到没,其实_get_backends就是获取了我们在settings总配置的AUTHENTICATION_BACKENDS元组,其实到这所有都一目了然,其实LoginView中的authenticate方法就是调用了我们自定义backend中authenticate方法,所以我们backend中的authenticate方法中username参数就是前端request请求中的POST属性中的username值,所以我们可以通过django中的Q对象来根据username或者email来获取用户。

三.总结

自定义验证方法的步骤
1.自定义Backend类并重构authenticate方法
2.settings中配置AUTHENTICATION_BACKENDS属性
3.编写相应view方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值