• 随机验证码


    一、验证码相关知识

    Python生成随机验证码,需要使用PIL模块.

    安装:

    pip3 install pillow

    基本使用

    1. 创建图片

    复制代码
    from PIL import Image
    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
      
    # 在图片查看器中打开
    # img.show()
      
    # 保存在本地
    with open('code.png','wb') as f:
        img.save(f,format='png')
    复制代码

    2. 创建画笔,用于在图片上画任意内容

    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    3. 画点

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示坐标
    4 # 第二个参数:表示颜色
    5 draw.point([100, 100], fill="red")
    6 draw.point([300, 300], fill=(255, 255, 255))

    4. 画线

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示起始坐标和结束坐标
    4 # 第二个参数:表示颜色
    5 draw.line((100,100,100,300), fill='red')
    6 draw.line((100,100,300,100), fill=(255, 255, 255))

    5. 画圆

    复制代码
    img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')
    # 第一个参数:表示起始坐标和结束坐标(圆要画在其中间)
    # 第二个参数:表示开始角度
    # 第三个参数:表示结束角度
    # 第四个参数:表示颜色
    draw.arc((100,100,300,300),0,90,fill="red")
    复制代码

    6. 写文本

    1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
    2 draw = ImageDraw.Draw(img, mode='RGB')
    3 # 第一个参数:表示起始坐标
    4 # 第二个参数:表示写入内容
    5 # 第三个参数:表示颜色
    6 draw.text([0,0],'python',"red")

    7. 特殊字体文字

    复制代码
     1 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
     2 draw = ImageDraw.Draw(img, mode='RGB')
     3 # 第一个参数:表示字体文件路径
     4 # 第二个参数:表示字体大小
     5 font = ImageFont.truetype("kumo.ttf", 28)
     6 # 第一个参数:表示起始坐标
     7 # 第二个参数:表示写入内容
     8 # 第三个参数:表示颜色
     9 # 第四个参数:表示颜色
    10 draw.text([0, 0], 'python', "red", font=font)
    复制代码

    图片验证码

    复制代码
     1 import random
     2   
     3 def check_code(width=120, height=30, char_length=5, font_file='kumo.ttf', font_size=28):
     4     code = []
     5     img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
     6     draw = ImageDraw.Draw(img, mode='RGB')
     7   
     8     def rndChar():
     9         """
    10         生成随机字母  
    11         :return:
    12         """
    13         return chr(random.randint(65, 90))
    14   
    15     def rndColor():
    16         """
    17         生成随机颜色
    18         :return:
    19         """
    20         return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
    21   
    22     # 写文字
    23     font = ImageFont.truetype(font_file, font_size)
    24     for i in range(char_length):
    25         char = rndChar()
    26         code.append(char)
    27         h = random.randint(0, 4)
    28         draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
    29   
    30     # 写干扰点
    31     for i in range(40):
    32         draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    33   
    34     # 写干扰圆圈
    35     for i in range(40):
    36         draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
    37         x = random.randint(0, width)
    38         y = random.randint(0, height)
    39         draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
    40   
    41     # 画干扰线
    42     for i in range(5):
    43         x1 = random.randint(0, width)
    44         y1 = random.randint(0, height)
    45         x2 = random.randint(0, width)
    46         y2 = random.randint(0, height)
    47   
    48         draw.line((x1, y1, x2, y2), fill=rndColor())
    49   
    50     img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    51     return img,''.join(code)
    52   
    53   
    54 if __name__ == '__main__':
    55     # 1. 直接打开
    56     # img,code = check_code()
    57     # img.show()
    58   
    59     # 2. 写入文件
    60     # img,code = check_code()
    61     # with open('code.png','wb') as f:
    62     #     img.save(f,format='png')
    63   
    64     # 3. 写入内存(Python3)
    65     # from io import BytesIO
    66     # stream = BytesIO()
    67     # img.save(stream, 'png')
    68     # stream.getvalue()
    69   
    70     # 4. 写入内存(Python2)
    71     # import StringIO
    72     # stream = StringIO.StringIO()
    73     # img.save(stream, 'png')
    74     # stream.getvalue()
    75   
    76     pass
    复制代码

    二、图片验证码应用

    四种实现方式,越来越趋于完美

    方式一:

     # 方式一:这样的方式吧路径写死了,只能是那一张图片
        import os
        path = os.path.join(settings.BASE_DIR,"static","image","3.jpg")  #路径拼接
        with open(path,"rb") as f:
            data = f.read()
        return HttpResponse(data)

    方式二:

    复制代码
    # 方式二:每次都显示不同的图片,利用pillow模块,安装一个pillow模块
        from PIL import Image
        img = Image.new(mode="RGB",size=(120,40),color="green") #首先自己创建一个图片,参数size=(120,40) 代表长和高
        f = open("validcode.png","wb")#然后把图片放在一个指定的位置
        img.save(f,"png")  #保存图片
        f.close()
        with open("validcode.png","rb") as f:
            data = f.read()
        return HttpResponse(data)
    复制代码

    方式三:

    复制代码
     # 方式三:
        # 方式二也不怎么好,因为每次都要创建一个保存图片的文件,我们可以不让吧图片保存到硬盘上,
        # 在内存中保存,完了自动清除,那么就引入了方式三:利用BytesIO模块
        from io import BytesIO
        from PIL import Image
        img = Image.new(mode="RGB",size=(120,40),color="blue")
        f = BytesIO()  #内存文件句柄
        img.save(f,"png")  #保存文件
        data = f.getvalue()#打开文件(相当于python中的f.read())
        return HttpResponse(data)
    复制代码

    方式四:

    复制代码
     # 方式四:1、添加画笔,也就是在图片上写上一些文字
        #         2、并且字体随机,背景颜色随机
        from io import BytesIO
        from PIL import Image,ImageDraw,ImageFont
        import random
        #随机创建图片
        img = Image.new(mode="RGB",size=(120,40),color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
        draw = ImageDraw.Draw(img,"RGB")
        # 画干扰线
        for i in range(5):
            x1 = random.randint(0, 120)
            y1 = random.randint(0, 40)
            x2 = random.randint(0, 120)
            y2 = random.randint(0, 40)
    
            draw.line((x1, y1, x2, y2), fill=(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
    
        font = ImageFont.truetype("static/font/kumo.ttf",20)  #20表示20像素
    
        str_list = []  #吧每次生成的验证码保存起来
        # 随机生成五个字符
        for i in range(5):
            random_num = str(random.randint(0, 9))  # 随机数字
            random_lower = chr(random.randint(65, 90))  # 随机小写字母
            random_upper = chr(random.randint(97, 122))  # 随机大写字母
            random_char = random.choice([random_num, random_lower, random_upper])
            print(random_char,"random_char")
            str_list.append(random_char)
            # (5 + i * 24, 10)表示坐标,字体的位置
            draw.text((5+i*24,10),random_char,(random.randint(0,255),random.randint(0,255),random.randint(0,255)),font=font)
        print(str_list,"str_list")
        f = BytesIO()#内存文件句柄
        img.save(f,"png")   #img是一个对象
        data = f.getvalue()  #读取数据并返回至HTML
        valid_str = "".join(str_list)
        print(valid_str,"valid_str")
        request.session["keep_valid_code"] = valid_str   #吧保存到列表的东西存放至session中
        return HttpResponse(data)
    复制代码

    项目加上验证码

    from PIL import Image, ImageDraw, ImageFont
    import random
    
    
    def random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    
    
    def v_code(request):
        img_obj = Image.new('RGB', (250, 35), random_color())
        
        # 在该图片对象上生成一个画笔对象
        draw_obj = ImageDraw.Draw(img_obj)
        
        font_obj = ImageFont.truetype('static/font/kumo.ttf', 28)
        
        temp = []
        for i in range(5):
            l = chr(random.randint(97, 122))  # 小写字母
            b = chr(random.randint(65, 90))  # 大写字母
            n = str(random.randint(0, 9))
            
            t = random.choice([l, b, n])
            temp.append(t)
            
            draw_obj.text((i * 40 + 35, 0), t, fill=random_color(), font=font_obj)
            
        # 加干扰线
        width = 250  # 图片宽度(防止越界)
        height = 35
        for i in range(5):
            x1 = random.randint(0, width)
            x2 = random.randint(0, width)
            y1 = random.randint(0, height)
            y2 = random.randint(0, height)
            draw_obj.line((x1, y1, x2, y2), fill=random_color())
        
        request.session['v_code'] = ''.join(temp).upper()
        
        from io import BytesIO
        f1 = BytesIO()
        img_obj.save(f1, format="PNG")
        img_data = f1.getvalue()
        
        return HttpResponse(img_data, content_type='image/png')
    
    
    def login(request):
        err_msg = ''
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            v_code = request.POST.get('v_code', '').upper()
            
            if v_code == request.session.get('v_code'):
                obj = auth.authenticate(request, username=username, password=password)
                if obj:
                    auth.login(request, obj)
                    # 认证成功 初始化权限信息
                    ret = init_permission(request, obj)
                    if ret:
                        return ret
                    return redirect(reverse('my_customer'))
                err_msg = '用户名或密码错误'
            else:
                err_msg = '验证码错误'
        
        return render(request, 'login.html', {'err_msg': err_msg})
    views.py
    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta http-equiv="content-Type" charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'css/reset.css' %}">
        <link rel="stylesheet" href="{% static 'css/style.css' %}">
    </head>
    <body>
    <div id="particles-js">
        <div class="login">
    
            <form action="" method="post">
                {% csrf_token %}
                <div class="login-top">
                    登录
                </div>
                <div class="login-center clearfix">
                    <div class="login-center-img"><img src="{% static 'imgs/name.png' %}"></div>
                    <div class="login-center-input">
                        <input type="text" name="username" value="admin" placeholder="请输入您的用户名"
                               onfocus="this.placeholder=''"
                               onblur="this.placeholder='请输入您的用户名'">
                        <div class="login-center-input-text">用户名</div>
                    </div>
                </div>
                <div class="login-center clearfix">
                    <div class="login-center-img"><img src="{% static 'imgs/password.png' %}"></div>
                    <div class="login-center-input">
                        <input type="password" name="password" value="" placeholder="请输入您的密码" onfocus="this.placeholder=''"
                               onblur="this.placeholder='请输入您的密码'">
                        <div class="login-center-input-text">密码</div>
                    </div>
                </div>
    
                <div class="login-center clearfix">
                    <div class="login-center-img"><img src="{% static 'imgs/password.png' %}"></div>
                    <div class="login-center-input">
                        <input type="text" name="v_code" value="" placeholder="请输入验证码" onfocus="this.placeholder=''"
                               onblur="this.placeholder='请输入验证码'">
                        <div class="login-center-input-text">验证码</div>
                    </div>
                </div>
                <div style="text-align: center">
                    <img src="{% url 'v_code' %}" alt="" id="v_code">
                </div>
    
                <p style="color: red;text-align: center">{{ err_msg }}</p>
                <div style="text-align: center">
                    <button class="login-button">登录</button>
                </div>
            </form>
        </div>
        <div class="sk-rotating-plane"></div>
        <canvas class="particles-js-canvas-el" width="1343" height="202" style=" 100%; height: 100%;"></canvas>
    </div>
    
    <script src="{% static 'js/particles.min.js' %}"></script>
    <script src="{% static 'js/app.js' %}"></script>
    
    <script>
        img = document.getElementById('v_code');
        img.onclick = function () {
            img.src += '?'
        }
    </script>
    
    <script type="text/javascript">
        function hasClass(elem, cls) {
            cls = cls || '';
            if (cls.replace(/s/g, '').length == 0) return false; //当cls没有参数时,返回false
            return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
        }
    
        function addClass(ele, cls) {
            if (!hasClass(ele, cls)) {
                ele.className = ele.className == '' ? cls : ele.className + ' ' + cls;
            }
        }
    
        function removeClass(ele, cls) {
            if (hasClass(ele, cls)) {
                var newClass = ' ' + ele.className.replace(/[	
    ]/g, '') + ' ';
                while (newClass.indexOf(' ' + cls + ' ') >= 0) {
                    newClass = newClass.replace(' ' + cls + ' ', ' ');
                }
                ele.className = newClass.replace(/^s+|s+$/g, '');
            }
        }
    
        document.querySelector(".login-button").onclick = function () {
            addClass(document.querySelector(".login"), "active")
            setTimeout(function () {
                addClass(document.querySelector(".sk-rotating-plane"), "active")
                document.querySelector(".login").style.display = "none"
            }, 800)
            setTimeout(function () {
                removeClass(document.querySelector(".login"), "active")
                removeClass(document.querySelector(".sk-rotating-plane"), "active")
                document.querySelector(".login").style.display = "block"
                alert("登录成功")
    
            }, 5000)
        }
    </script>
    
    </body>
    </html>
    login.html
    #  ###### 权限相关的配置 ######
    PERMISSION_SESSION_KEY = 'permissions'
    MENU_SESSION_KEY = 'menus'
    WHITE_URL_LIST = [
        r'/login/$',
        r'^/logout/$',
        r'^/reg/$',
        r'^/admin/.*',
        r'^/v_code/.*',
    ]
    白名单


    三、滑动验证码应用

     我们可以借助插件来做

    1、打开插件,找到自己需要的验证码

    2、筛选有用的路径

    3、把对应的视图函数也拿过来,注意还需要一个geetest.py的文件

    具体实现

    幻想毫无价值,计划渺如尘埃,目标不可能达到。这一切的一切毫无意义——除非我们付诸行动。
  • 相关阅读:
    day02_07 创建新目录
    day02_04 字典
    day02_02 列表切割
    day03_01 文件操作
    MS的TREE 控件使用
    使用自定义用户控件的一些经验
    Asp.net开发心得点滴[动态加载的用户控件使用事件委托,交给页面处理的事件无效问题]
    正则表达式基础学习[1]
    自定义控件无法在VS.net编辑中显示
    错误的递归
  • 原文地址:https://www.cnblogs.com/TodayWind/p/13884932.html
Copyright © 2020-2023  润新知