• BBS


     

      基于用户认证组件和Ajax实现登录验证(图片验证码)

      UserInfo表既有原生auth_user表的字段,又有你扩展的字段,以后用的接口UserInfo既是自己的用户表又是原生认证组件的用户表

    一.登录页面的设计

      login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    </head>
    <body>
    
        <h3>登录页面</h3>
    
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3" >
                    <form>
                        {% csrf_token %}
                        <div class="form-group">
                            <label for="user">用户名</label>
                            <input type="text" id="user" class="form-control">
                        </div>
                        <div class="form-group">
                            <label for="pwd">密码</label>
                            <input type="password" id="pwd" class="form-control">
                        </div>
    
                        <div class="form-group">
                            <label for="">验证码</label>
                            <div class="row">  {# 独立一行 #}
                                {# 各占一半 #}
                                <div class="col-md-6">
                                    <input type="text" id = "valid_code" class="form-control">
                                </div>
                                <div class="col-md-6">
                                    <img width="265" height="38" id="valid_code_img" src="/get_valid_img/" alt="">
                                </div>
                            </div>
                        </div>
                        <input type="button" class="btn btn-default login_btn " value="submit"><span class="error"></span>
                        <a href="/register/" class="btn btn-success pull-right">注册</a>
                    </form>
                </div>
            </div>
        </div>

    二.验证码图片的生成

      validCode.py

    # -*- coding:utf-8 -*-
    import random
    
    
    def get_random_color(): # 生成随机颜色三要素
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    
    
    def get_valid_code_img(request):
    
        # 方式一:写死了
        # with open("kobe.jpg", "rb") as f:
        #     data = f.read()
        # return HttpResponse(data)
    
        # 方式二:磁盘中 速度慢 # pip install pillow  # 图像处理模块
        # from PIL import Image
        # img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color) 长度265 高度38
        #
        # # 生成随机图片
        # with open("validCode.png", "wb") as f: # 先加到磁盘上
        #     img.save(f, "png")  # 会生成一个叫validCode.png的图片
        #
        # # 读出图片
        # with open("validCode.png", "rb") as f:
        #     data = f.read()
    
        # 方式三:放在内存中
        # from PIL import Image
        # from io import BytesIO   # BytesIO就是内存管理
        # img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color)
        #
        # f = BytesIO()  # 内存句柄
        # img.save(f, "png")  # save到内存中
        # data = f.getvalue()  # 读数据
    
        # 方式四:放在内存中, 添加文字
        from PIL import Image, ImageDraw, ImageFont  # ImageDraw是画笔,ImageFont是字体大小
        from io import BytesIO
        img = Image.new("RGB", (265, 38), color=get_random_color())  # Image.new(mode,size,color)
    
        draw = ImageDraw.Draw(img)  # 在img中画东西,draw.text()写文字,draw.line()画线,draw.point()画点
        kumo_font = ImageFont.truetype("static/fonts/KumoFont.ttf", size=30) # 参数为字体路径和大小
    
        # global valid_code_str
        valid_code_str = ""
        for i in range(6):
            random_num = str(random.randint(0, 9))
            random_low_alpha = chr(random.randint(97, 122))
            random_upper_alpha = chr(random.randint(65, 90))
    
            random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
    
            # text(self, xy, text, fill=None, font=None, anchor=None,*args, **kwargs)
            # xy:坐标 text:文字 fill:颜色 font:字体
            draw.text(((30*i+45), 5), random_char, get_random_color(), font=kumo_font)
    
            # 保存验证码字符串
            valid_code_str += random_char
    
        f = BytesIO()  # 内存句柄
        img.save(f, "png")
        data = f.getvalue()  # 读数据
    
        return data

    噪声噪线

      validCode.py

    补充躁点躁线, 防止机器
        width = 265  # 要跟上边的宽高一致
        height = 38
    
        for i in range(10):
            x1 = random.randint(0, width)
            x2 = random.randint(0, width)
            y1 = random.randint(0, height)
            y2 = random.randint(0, height)
            draw.line((x1, y1, x2, y2), fill=get_random_color())
    
        for i in range(80):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
            x = random.randint(0, width)
            y = random.randint(0, height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())

    三.验证码刷新

    $("#valid_code_img")[0]
    <img width=​"270" height=​"40" id=​"valid_code_img" src=​"http:​/​/​127.0.0.1:​8000/​get_validCode_img/​??" alt>​
     $("#valid_code_img")[0].src
    "http://127.0.0.1:8000/get_validCode_img/??"
    
     $("#valid_code_img")[0].src+="?"  #+="?"添加一次这个就刷新一次验证码
    "http://127.0.0.1:8000/get_validCode_img/???"
     $("#valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/get_validCode_img/????"
     $("#valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/get_validCode_img/?????"
     $("#valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/get_validCode_img/??????"
     $("#valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/get_validCode_img/???????"

      login.html

    <script src="/static/js/jquery-3.3.1.js"></script>
        <script>
            {# 刷新验证码,不用ajax也可以 #}
            $("#valid_code_img").click(function () {
                $(this)[0].src += "?"
            });
        </script>

    四.保存验证码字符串

       validCode.py

    valid_code_str = "" #保存验证码字符串,这样才能验证
        for i in range(5):
            random_num = str(random.randint(0,9))
            random_low_alpha = chr(random.randint(95,122))
            random_upper_alpha = chr(random.randint(65,90))
            random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
            draw.text((i*50+20, 5), random_char, get_random_color(), font=kumo_font)
    
            #保存验证码字符串
            valid_code_str += random_char #做一个累加
    
        print("valid_code_str", valid_code_str)
        request.session["valid_code_str"] = valid_code_str  #保存它,写一个session
    
        '''
        1 sdajsdq33asdf #生成一个随机字符串,
        2 COOKIE {"sessionid":sdajsdq33asdf} #设置一个cookie,返回给cookie那边一个键叫sessionid,值是随机字符串
        3 django-session   #数据部分保存到了django_session;在session表进行存储
          session-key   session-data
          sdajsdq33asdf  {"valid_code_str":"12345"}
        '''
    
        f = BytesIO()
        img.save(f,"png")
        data = f.getvalue()
    
        return HttpResponse(data)

    五.登录验证

    #global valid_code_str 这里不能把它变成全局变量,这时虽然校验时可以拿到valid_code_str,但如果是两个人一块访问,那么那个验证码的值存的是最后一个人访问(刷新)的,前面那个人那个就取不到了应该每个人的单独保存,使用会话跟踪技术,把每个人校验的值存到cookie里边

      views.py

    # -*- encoding:utf-8 -*-
    from django.shortcuts import render, HttpResponse, redirect
    
    import random
    # Create your views here.
    from django.http import JsonResponse
    from django.contrib import auth
    
    def login(request):
    
        if request.method == "POST":
    
            response = {"user": None, "msg": None} # 先构建一个字典,"user":None默认没有登录成功,"msg"里边放错误信息
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            valid_code = request.POST.get("valid_code")
    
            # global valid_code_str,不能使用这种方法,因为当多个人同时登录的时候valid_code_str会被覆盖掉,会产生混淆
            # 使用会话跟踪技术,session来保存每个人的验证码,request.session["valid_code_str"] = valid_code_str
            valid_code_str = request.session.get("valid_code_str")
            if valid_code.upper() == valid_code_str.upper():    # 验证验证码,不区分大小写
    
                #  验证用户名密码
                user = auth.authenticate(username=user, password=pwd) # 用户认证组件
                if user:  # 把这个user注册进去,只要登录成功了,request.user就是当前登录对象用户,否则它就是个匿名对象
                    auth.login(request, user)  # requese.user 当前登录对象,登录成功在这里不能跳转,用的是ajax请求而不是form请求,ajax请求只接收一个数据data
                    response["user"] = user.username
                else:
                    response["msg"] = "用户名或者密码错误!"
            else:
                response["msg"] = "验证码错误!"
    
            return JsonResponse(response) # 直接把字典放里面,它帮我们序列化,而且在ajax那边直接拿到对象也不用反序列化
    
        return render(request, 'login.html')
    
    def index(request):
    
        return render(request, "index.html")

      login.html

    {# ajax登录验证 #}
            $(".login_btn").click(function () {
                $.ajax({
                    url:"",
                    type:"post",
                    data:{
                        user:$("#user").val(), {# 获取用户名输入数据 #}
                        pwd:$("#pwd").val(), {# 获取密码输入数据 #}
                        valid_code:$("#valid_code").val(), {# 获取验证码输入数据 #}
                        csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()   {# 必须加这个键值对才能通过校验 #}
                    },
                    success:function (data) {
                        console.log(data);
    
                        if (data.user){  {# 判断有没有值,出错就把错误信息显示在页面上 #}
                            location.href = "/index/" {# 登录成功就跳转到index页面 #}
                        }
                        else {
                            $(".error").text(data.msg).css({"color": "red", "margin-left":"20px"})
    
                            {# 规定时间清空错误信息 #}
                            setTimeout(function () {
                                $(".error").text("")
                            }, 1000)
                        }
                    }
                })
            })
    总结:
    1 一次请求伴随多次请求
    2 PIL
    3 session存储
    4 验证码刷新

    附:

    滑动验证码--->引入这样一个插件

    要先把social-auth-app-django下载下来

    C:UsersAdministrator>pip install social-auth-app-django
    Collecting social-auth-app-django

    把它嵌入到我们的代码里边

  • 相关阅读:
    最近要看的项目
    Lavarel Route::resource
    架构,性能
    Unity ToLua & LuaFramework_UGUI学习笔记(zz)
    Unity UI 布局
    Introduction to Unity UI
    Unity more efficient find
    unity UI如何开启(显示)或者关闭(隐藏)Panel界面最好?
    Unity Canvas vs Panel
    Unity实现新手引导圆形遮罩
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/10417819.html
Copyright © 2020-2023  润新知