• 2-功能1:基于用户认证组件和Ajax实现登录验证(图片验证码)


    1、登录页面的设计

     (1)label标签的id属性

    label标签的id属性,点击label标记,相当于点击了input框
    
    bootstarp样式
        class="form-group"
        class="form-control"

    (2)此时的验证码先取静态路径

                    <div class="form-group">
                        <label for="id_valid_code_str">验证码</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" id="id_valid_code_str" class="form-control">
                            </div>
                            <div class="col-md-6">
                                <img src="/blog/get_validCode/" id="id_valid_code_img" width="270" height="35" title="验证码" alt="">
                            </div>
                        </div>
                    </div>

     2、验证码图片的生成

     

     

    (1)方式1:HttpResponse返回字符串



    (2)方式2:引入PIL模块  pip install pillow

    from PIL import Image
    import random
    
    
    def get_random_color():
        """生成随机颜色(255,255,255)"""
        return tuple([random.randint(0, 255) for _ in range(3)])
    
    
    def get_validCode(request):
        # 在本地生成一张图片validCode.png
        img = Image.new("RGB", (270, 35), color=get_random_color())
        with open("validCode.png", 'wb') as f:
            img.save(f, 'png')
            
        with open('validCode.png', 'rb') as f:
            data = f.read()
    
        return HttpResponse(data)

     (3)方式3:内存处理

    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    import random
    
    
    def get_random_color():
        """生成随机颜色(255,255,255)"""
        return tuple([random.randint(0, 255) for _ in range(3)])
    
    
    def get_validCode(request):
        
        # 在内存生成一张图片validCode.png
        img = Image.new('RGB', (210, 35), color=get_random_color())
        f = BytesIO()
        img.save(f, 'png')
        data = f.getvalue()
    
        return HttpResponse(data)

    (4)方式4:加入噪点的,字体的

    # 方式4:加入噪点的
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    import random
    import string   # string字符串
    
    def get_random_color():
        return tuple([random.randint(0, 255) for _ in range(3)])
    
    
    def get_validCode(request):
        holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体
    
        img = Image.new('RGB', (210, 35), color=get_random_color())
        draw = ImageDraw.Draw(img)  # 在img上作画
    
        # draw.text()     # 文字
        # draw.line()     # 线
        # draw.point()    # 点
    
        # draw数字字母5个
        for i in range(5):
            random_char = random.choice(string.digits + string.ascii_letters)
            draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)
    
        # 补充噪点噪音
        width, height = 210, 35
        for i in range(100):
            x1 = random.randint(0, width)
            x2 = random.randint(0, width)
            y1 = random.randint(0, width)
            y2 = random.randint(0, width)
            draw.line((x1, y1, x2, y2), fill=get_random_color())
    
        for i in range(400):
            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())
    
        # 内存处理
        f = BytesIO()
        img.save(f, 'png')
        data = f.getvalue()
    
        return HttpResponse(data)

        

     3、验证码的刷新与字符串保存,验证码解耦

    (1)刷新

    $("#id_valid_code_img")
    [img#id_valid_code_img]
    $("#id_valid_code_img")[0]
    <img src=​"/​blog/​get_validCode/​" id=​"id_valid_code_img" width=​"270" height=​"35" title=​"验证码" alt>​
    $("#id_valid_code_img")[0].src
    "http://127.0.0.1:8000/blog/get_validCode/"
    $("#id_valid_code_img")[0].src+="?"    # 页面刷新
    "http://127.0.0.1:8000/blog/get_validCode/?"  
    $("#id_valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/blog/get_validCode/??"
    $("#id_valid_code_img")[0].src+="?"
    "http://127.0.0.1:8000/blog/get_validCode/???"

     模板层 js代码

    <script type="text/javascript">
        //刷新验证码
        $(function () {
            $("#id_valid_code_img").click(function () {
                $(this)[0].src+="?"
            })
        })
    </script>

    (2)保存验证码字符串

    (3)多个用户同时访问验证码

    全局变量不可取

    (4)session存储验证码字符串

     

     (5)验证码解耦

    validCode.py

    # 方式4:加入噪点的
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    import random
    import string  # string字符串
    
    
    def get_random_color():
        return tuple([random.randint(0, 255) for _ in range(3)])
    
    
    def get_validCode_img(request):
        holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体
    
        img = Image.new('RGB', (210, 35), color=get_random_color())
        draw = ImageDraw.Draw(img)  # 在img上作画
    
        # draw数字字母5个
        valid_code_str = ""  # 保存验证码字符串
        for i in range(5):
            random_char = random.choice(string.digits + string.ascii_letters)
            draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)
            valid_code_str += random_char
    
        print("valid_code_str", valid_code_str)
    
        # 把验证码放入session中
        request.session["valid_code_str"] = valid_code_str
    
        # 内存处理
        f = BytesIO()
        img.save(f, 'png')
        data = f.getvalue()
    
        return data

     views.py视图

    from django.shortcuts import render, HttpResponse, redirect
    from blog.utils.validCode import get_validCode_img      # 导入验证码函数
    
    
    def login(request):
        return render(request, 'blog/login.html')
    
    
    def get_validCode(request):
        """
        基于PIL模块动态生成响应状态码图片
        :param request: 
        :return: 
        """
        data = get_validCode_img(request)
        return HttpResponse(data)

    4、登录验证 

    (1)ajax流程图

     

    (2)用户认证auth模块,ajax信息response

    (3)ajax  success成功执行

     

     

       (4)代码优化:错误信息1s后消失

     (5)完整代码

    主url

    from django.contrib import admin
    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^blog/', include(('blog.urls', 'blog')))
    ]
    View Code

    url

    from django.urls import path, re_path
    from blog import views
    from django.views.static import serve
    from cnblog import settings
    
    urlpatterns = [
        re_path('^login/$', views.login, name='login'),
        re_path('^get_validCode/$', views.get_validCode, name='get_validCode'),
        re_path('^index/$', views.index, name='index'),
    ]

    view视图

    from django.shortcuts import render, HttpResponse, redirect
    from blog.utils.validCode import get_validCode_img  # 导入验证码函数
    from django.http import JsonResponse  # Json数据返回到前端
    from django.contrib import auth     # 用户认证组件
    
    
    def login(request):
        if request.method == "POST":
            response = {'user': None, "msg": None}
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            valid_code_str = request.POST.get("valid_code_str")
    
            _valid_code_str = request.session.get("valid_code_str")
    
            # 验证码验证
            if valid_code_str.upper() == _valid_code_str.upper():
    
                # 用户认证
                user = auth.authenticate(username=user, password=pwd)
                if user:
                    auth.login(request, user)   # request.user == 当前登录对象
                    response["user"] = user.username
                else:
                    response["msg"] = "用户名或者密码错误"
    
            else:
                response['msg'] = "验证码错误"
    
            return JsonResponse(response)
    
        return render(request, 'blog/login.html')
    
    
    def get_validCode(request):
        """
        基于PIL模块动态生成响应状态码图片
        :param request:
        :return:
        """
        data = get_validCode_img(request)
        return HttpResponse(data)
    
    def index(request): return HttpResponse(request.user.username)

    utils工具包:验证码解耦

    # 方式4:加入噪点的
    from PIL import Image, ImageDraw, ImageFont
    from io import BytesIO
    import random
    import string  # string字符串
    
    
    def get_random_color():
        return tuple([random.randint(0, 255) for _ in range(3)])
    
    
    def get_validCode_img(request):
        holly_font = ImageFont.truetype('static/font/holly.ttf', size=28)  # 字体
    
        img = Image.new('RGB', (210, 35), color=get_random_color())
        draw = ImageDraw.Draw(img)  # 在img上作画
    
        # draw数字字母5个
        valid_code_str = ""  # 保存验证码字符串
        for i in range(5):
            random_char = random.choice(string.digits + string.ascii_letters)
            draw.text((i * 40 + 20, 5), random_char, get_random_color(), font=holly_font)
            valid_code_str += random_char
    
        print("valid_code_str", valid_code_str)
    
        # 把验证码放入session中
        request.session["valid_code_str"] = valid_code_str
    
        # 内存处理
        f = BytesIO()
        img.save(f, 'png')
        data = f.getvalue()
    
        return data

    模板层

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
        <script src="/static/js/jquery-3.2.1.min.js"></script>
    </head>
    <body>
    
    <h3>登录页面</h3>
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
                <form>
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="id_username">用户名</label>
                        <input type="text" id="id_username" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="id_password">密码</label>
                        <input type="password" id="id_password" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="id_valid_code_str">验证码</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" id="id_valid_code_str" class="form-control">
                            </div>
                            <div class="col-md-6">
                                <img src="/blog/get_validCode/" id="id_valid_code_img" width="270" height="35" title="验证码"
                                     alt="">
                            </div>
                        </div>
                    </div>
                    <input type="button" class="btn btn-default login-btn" value="登录"><span class="error"></span>
    
                </form>
            </div>
        </div>
    </div>
    </body>
    
    </html>

    ajax代码

    <script type="text/javascript">
        //刷新验证码
        $(function () {
            $("#id_valid_code_img").click(function () {
                $(this)[0].src += "?"
            })
        });
    
        //登录验证
        $(function () {
            $('.login-btn').click(function () {
                $.ajax({
                    url: '',
                    type: 'post',
                    data: {
                        user: $("#id_username").val(),
                        pwd: $("#id_password").val(),
                        valid_code_str: $("#id_valid_code_str").val(),
                        csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
    
                    },
                    success: function (data) {
                        console.log(data)
    
                        if (data.user) {
                            location.href = "/blog/index"
                        }
                        else {
                            $('.error').text(data.msg).css({'color': 'red', 'margin-left': '20px'});
    
                            //定时器 1s后error_msg 消失
                            setTimeout(function () {
                                $('.error').text("")
                            }, 1000)
                        }
                    }
    
                })
            })
        })
    </script>

     (6)滑动验证码:django-demo

     

     

       (7)总结

    总结: 
       1 一次请求伴随多次请求
    
       2 PIL     
            # 生成验证码图片
    
       3 session存储  
            # 把验证码放入session中
            request.session["valid_code_str"] = valid_code_str
    
       4 验证码刷新    
            //刷新验证码
            $(function () {
                $("#id_valid_code_img").click(function () {
                    $(this)[0].src += "?"
                })
            });    

     

  • 相关阅读:
    【BZOJ1029】[JSOI2007] 建筑抢修(堆优化贪心)
    【CF799B】T-shirt buying(一道很水的小根堆)
    【BZOJ1076】[SCOI2008] 奖励关(状压DP)
    【BZOJ1087】[SCOI2005] 互不侵犯King(状压DP)
    【BZOJ3209】花神的数论题(数位DP)
    【BZOJ1833】[ZJOI2010] count 数字计数(数位DP)
    【洛谷】CYJian的水题大赛 解题报告
    【洛谷3959】宝藏(随机算法乱搞)
    【洛谷2709】小B的询问(莫队模板题)
    【洛谷2403】[SDOI2010] 所驼门王的宝藏(Tarjan+dfs遍历)
  • 原文地址:https://www.cnblogs.com/venicid/p/9365977.html
Copyright © 2020-2023  润新知