zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/10417819.html
Copyright © 2011-2022 走看看