【Django基础】Django编写图形验证码

下载字体

到https://files-cdn.cnblogs.com/files/wupeiqi/%E9%AA%8C%E8%AF%81%E7%A0%81%E5%AD%97%E4%BD%93%E6%96%87%E4%BB%B6.zip

生成图形验证码函数

from PIL import Image, ImageDraw, ImageFilter, ImageFont
import random
 

def check_code(width=120, height=30, char_length=5, font_file='employee_management/utils/ttf/Monaco.ttf', font_size=28):
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')
 
    def rndChar():
        """
        生成随机字母   
        :return:
        """
        return chr(random.randint(65, 90))
 
    def rndColor():
        """
        生成随机颜色
        :return:
        """
        return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
 
    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
 
    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
 
    # 写干扰圆圈
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
 
    # 画干扰线
    for i in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
 
        draw.line((x1, y1, x2, y2), fill=rndColor())
 
    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img,''.join(code)


if __name__ == '__main__':
    img, code_str = check_code()
    print(code_str)

    with open('code.png', 'wb') as f:
        img.save(f, format='png')

获取验证码

# views.py函数
def image_code(request):
    """ 生成图片验证码 """
    # 调用pillow函数,生成图片
    img, code_string = check_code()

    # 写入到自己的session中,以便于后续获取验证码再进行校验
    request.session['image_code'] = code_string
    # 给session设置 60s 超时
    request.session.set_expiry(60)

    stream = BytesIO()
    img.save(stream, 'png')
    return HttpResponse(stream.getvalue())  

验证码校验

def login(request):
    """登录"""
    if request.method == "GET":
        form = LoginForm()
        return render(request, 'login.html', {"form": form})

    form = LoginForm(data=request.POST)
    if form.is_valid():
        # 验证成功, 获取到的用户名和密码
        print(form.cleaned_data)
        # {'username': '123', 'password': '123'}
        # {'username': '456', 'password': '0f54af32f41a5ba8ef3a2d40cd6ccf25'}

        # 验证码的校验
        user_input_code = form.cleaned_data.pop('code')
        image_code = request.session.get('image_code', "")
        print("user_input_code={}, image_code={}".format(user_input_code, image_code))
        if image_code.upper() != user_input_code.upper():
            form.add_error("code", "验证码错误")
            return render(request, 'login.html', {"form": form})

        # 去数据库校验用户名和密码是否正确
        admin_object = Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password", "用户名或密码错误")
            return render(request, 'login.html', {"form": form})

        # 如果用户名密码和验证码正确
        # 网站生成随机字符创,写到用户浏览器的cookie中,再写入到服务器的session中
        request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
        # 重新设置session的超时时间,因为之前设置的session的超时时间的 60s
        request.session.set_expiry(60 * 60 * 24)

        return redirect("/admin/list/")

    return render(request, 'login.html', {"form": form})

刷新验证码

第一种

<img src="/image/code/" alt="" id="image_code" onclick="this.setAttribute('src','/image/code/?random='+Math.random())">

第二种

将图片验证码设置ID,并将ID绑定一个事件

// 设置ID
...
...

{% if field.name == 'code' %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        <div class="row">
                            <div class="col-xs-7">
                                {{ field }}
                                <span class="error-msg">{{ field.errors.0 }}</span>
                            </div>
                            <div class="col-xs-5">
                                <img src="{% url 'image_code' %}" id="imageCode" title="点击更换图片">
                            </div>
                        </div>
                    </div>
                {% else %}

...
...

// 绑定事件
...
...
{% block js %}
    <script>
        $(function () {
            $('#imageCode').click(function () {
                var oldSrc = $(this).attr('src');
                $(this).attr('src', oldSrc + "?");
            })
        })
    </script>
{% endblock %}
posted @ 2023-08-23 18:11  小C学安全  阅读(89)  评论(0)    收藏  举报