• 35)django-验证码


    一:验证码原理 

      第一次访问GET,后台:

        1.创建一张图片
        2.在图片中写入随机字符串
        3.将图片写到制定文件
        4.打开指定目录文件,读取内容
      5.把生成的验证码保存在session中 6. 通过HttpResponse()把图片反馈给前端
      
      提交POST:获取用户提交的POST和session的验证码比较。
    1)比如登陆页面验证
      可以生成两个连接,一个只生成文本,比如用户名等
        另一个生成图片。在点图片的时候只刷新这个页面。
      如果是一个页面,刷新的时候整个页面都刷新了。
    如下面页面中<img src指向了新页面>
    
        <div class="form-group">
            <label for="password">验证码</label>
    
            <div class="row">
                <div class="col-xs-7">
                    <input type="password" class="form-control" id="password" name="code" placeholder="请输入验证码">
                </div>
                <div class="col-xs-5">
                    <img src="/check_code.html">
                </div>
            </div>
    
        </div>
    
    2)正常登陆可能有多个人,每个的验证码是不同的。所以要加验证码保存在session中。
    流程:
        1.访问页面/login/
            -创建一个图片并组用户返回
            -Session存验证玛
        2.POST的时候
            比对验证码和session一样。
    
    3)台后生图片
        1.创建一张图片
        2.在图片中写入随机字符串
         假定:data=Object()
        3.将图片写到制定文件
        4.打开指定目录文件,读取内容
        5.HttpResponse(data)
    
    
    def check_code(request):
        """
        验证码
        :param request:
        :return:
        """
        stream = BytesIO()                      #生成字节对象(在内存中)
        img, code = create_validate_code()      #创建验证码,返回img对象,和code
        img.save(stream, 'PNG')                 #保存img到内在中,PNG是后缀(需要手动保存)
        request.session['CheckCode'] = code     #code保存到session中
        return HttpResponse(stream.getvalue())  #从内存中取图像,返回给前端页面。
    
    def login(request):
        """
        登陆
        :param request:
        :return:
        """
        if request.method == "POST":
            #验证码比对
            if request.session['CheckCode'].upper() == request.POST.get('check_code').upper():
                pass
            else:
                print('验证码错误')
    
    
        return render(request, 'login.html')
    

    二:验证码更新

      验证玛更换:其实就是刷新换新的URL地址,

      后台HttpResponse每次刷新生成的值都不一样

       <div class="form-group">
        <label for="password">验证码</label>
    
        <div class="row">
            <div class="col-xs-7">
                <input type="text" class="form-control" id="check_code" name="code" placeholder="请输入验证码" >
            </div>
            <div class="col-xs-5">
                #绑定onclick事件
                <img id="imgcode" src="/check_code.html" onclick="changeCode(this);">
            </div>
        </div>
    
      </div>
    
    <script>
        function changeCode(ths){ //ths是传递自己
            //给img更换新的地址,这里的ths.src=ths.src后面是新的url地址,
            // 但是这样页面不刷新(浏览器对相同的URL不做刷新,在后面加?来更改(URL加多个?都不影响)。原来的?是跟传递参数的,所以这样写没有问题(其实就是刷新换新的URL地址,后台HttpResponse每次刷新生成的值都不一样)
            ths.src=ths.src+"?"
        }
    </script>

    三:示例

    ##示例
        #utils下面check_code.py
    
        #!/usr/bin/env python
        # -*- coding:utf-8 -*-
        
        import random
        from PIL import Image, ImageDraw, ImageFont, ImageFilter
        
        _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
        _upper_cases = _letter_cases.upper()  # 大写字母
        _numbers = ''.join(map(str, range(3, 10)))  # 数字
        init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
        
        
        def create_validate_code(size=(120, 30),
                                 chars=init_chars,
                                 img_type="GIF",
                                 mode="RGB",
                                 bg_color=(255, 255, 255),
                                 fg_color=(0, 0, 255),
                                 font_size=18,
                                 font_type="Monaco.ttf",
                                 length=4,
                                 draw_lines=True,
                                 n_line=(1, 2),
                                 draw_points=True,
                                 point_chance=2):
            """
            @todo: 生成验证码图片
            @param size: 图片的大小,格式(宽,高),默认为(120, 30)
            @param chars: 允许的字符集合,格式字符串
            @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
            @param mode: 图片模式,默认为RGB
            @param bg_color: 背景颜色,默认为白色
            @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
            @param font_size: 验证码字体大小
            @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
            @param length: 验证码字符个数
            @param draw_lines: 是否划干扰线
            @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
            @param draw_points: 是否画干扰点
            @param point_chance: 干扰点出现的概率,大小范围[0, 100]
            @return: [0]: PIL Image实例
            @return: [1]: 验证码图片中的字符串
            """
        
            width, height = size  # 宽高
            # 创建图形
            img = Image.new(mode, size, bg_color)
            draw = ImageDraw.Draw(img)  # 创建画笔
        
            def get_chars():
                """生成给定长度的字符串,返回列表格式"""
                return random.sample(chars, length)
        
            def create_lines():
                """绘制干扰线"""
                line_num = random.randint(*n_line)  # 干扰线条数
        
                for i in range(line_num):
                    # 起始点
                    begin = (random.randint(0, size[0]), random.randint(0, size[1]))
                    # 结束点
                    end = (random.randint(0, size[0]), random.randint(0, size[1]))
                    draw.line([begin, end], fill=(0, 0, 0))
        
            def create_points():
                """绘制干扰点"""
                chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]
        
                for w in range(width):
                    for h in range(height):
                        tmp = random.randint(0, 100)
                        if tmp > 100 - chance:
                            draw.point((w, h), fill=(0, 0, 0))
        
            def create_strs():
                """绘制验证码字符"""
                c_chars = get_chars()
                strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开
        
                font = ImageFont.truetype(font_type, font_size)
                font_width, font_height = font.getsize(strs)
        
                draw.text(((width - font_width) / 3, (height - font_height) / 3),
                          strs, font=font, fill=fg_color)
        
                return ''.join(c_chars)
        
            if draw_lines:
                create_lines()
            if draw_points:
                create_points()
            strs = create_strs()
        
            # 图形扭曲参数
            params = [1 - float(random.randint(1, 2)) / 100,
                      0,
                      0,
                      0,
                      1 - float(random.randint(1, 10)) / 100,
                      float(random.randint(1, 2)) / 500,
                      0.001,
                      float(random.randint(1, 2)) / 500
                      ]
            img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲
        
            img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)
        
            return img, strs
    
        #views.py
        from utils.check_code import create_validate_code
        
        
        def check_code(request):
            """
            验证码
            :param request:
            :return:
            """
            stream = BytesIO()
            img, code = create_validate_code()
            img.save(stream, 'PNG')
            request.session['CheckCode'] = code
            return HttpResponse(stream.getvalue())
        
        
        def login(request):
            """
            登陆
            :param request:
            :return:
            """
            if request.method == "POST":
                if request.session['CheckCode'].upper() == request.POST.get('check_code').upper():
                    pass
                else:
                    print('验证码错误')
        
        
            return render(request, 'login.html')
    
    
        #login.html
        <!DOCTYPE html>
        <html>
        <head lang="en">
            <meta charset="UTF-8">
            <title></title>
            <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"/>
            <link rel="stylesheet" href="/static/plugins/font-awesome/css/font-awesome.css"/>
            <link rel="stylesheet" href="/static/css/edmure.css"/>
            <link rel="stylesheet" href="/static/css/commons.css"/>
            <link rel="stylesheet" href="/static/css/account.css"/>
            <style>
        
            </style>
        </head>
        <body>
        <div class="login">
            <div style="font-size: 25px; font-weight: bold;text-align: center;">
                用户登陆
            </div>
            <form role="form">
                <div class="form-group">
                    <label for="username">用户名</label>
                    <input type="text" class="form-control" id="username" name="username" placeholder="请输入用户名">
                </div>
                <div class="form-group">
                    <label for="password">密码</label>
                    <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码">
                </div>
                <div class="form-group">
                    <label for="password">验证码</label>
        
                    <div class="row">
                        <div class="col-xs-7">
                            <input type="text" class="form-control" id="check_code" name="code" placeholder="请输入验证码" >
                        </div>
                        <div class="col-xs-5">
                            <img id="imgcode" src="/check_code.html" onclick="changeCode(this);">
                        </div>
                    </div>
        
                </div>
                <div class="checkbox">
                    <label>
                        <input type="checkbox"> 一个月内自动登陆
                    </label>
                    <div class="right">
                        <a href="#">忘记密码?</a>
                    </div>
                </div>
                <button type="submit" class="btn btn-default">登 陆</button>
            </form>
        </div>
            <script>
                function changeCode(ths){ //ths是传递自己
                    //给img更换新的地址,这里的ths.src=ths.src后面是新的url地址,
                    // 但是这样页面不刷新(浏览器对相同的URL不做刷新,在后面加?来更改。原来的?是跟传递参数的,所以这样写没有问题
                    ths.src=ths.src+"?"
                }
            </script>
        </body>
    </html>
    View Code
     
  • 相关阅读:
    解决CollectionView TableView reloadData或者reloadSections时的刷新的闪烁问题
    HTTP请求头
    Fastlane 使用笔记
    python-函数式编程
    python-高级特性
    python基础使用
    python基础-函数02
    python基础-函数01
    python基础
    Linux基础
  • 原文地址:https://www.cnblogs.com/lixiang1013/p/7900119.html
Copyright © 2020-2023  润新知