(登录)Python生成图片验证码

1,生成图片

先安装  pip install Pillow

 

 

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


# char_length 验证码字母个数
def check_code(width=120, height=30, char_length=4, font_file='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:
"""
if random.randint(0, 9)%2==0:
return str(random.randint(0, 9)) # 加数字

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(4):
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)

 

 

 

 

from io import BytesIO
def image_code(request):
    '''生成图片验证码'''
    #调用pillow函数,生成图片
    img,code_string=check_code()

    #把code_string写入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():
        #验证成功,获取用户名和密码,在数据库中校验
        #验证码校验
        user_input_code=form.cleaned_data.pop('code')
        code=request.session.get("image_code","")
        if code.upper()!=user_input_code.upper():
            form.add_error("code","验证码错误")
            return render(request,'login.html',{'form':form})

        #前提:Admin中的字段名=form.cleaned_data的字段名
        admin_object=models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password","用户名或密码错误")
           # form.add_error("username","用户名或密码错误")
            return render(request, 'login.html', {"form": form})

        #用户名和密码正确
        #网站生成随机字符串;写到用户浏览器的cookie中;写到session中
        request.session['info']={'id':admin_object.id,'name':admin_object.username}
        #session保存7天
        request.session.set_expiry(60*60*24*7)
        return redirect('/admin/list')

    #输入的数据,检验失败
    return render(request, 'login.html', {"form": form})

 

 

 

 

<div class="form-group">
            <label for="id_code">图片验证码</label>
            <div class="row">
                <div class="col-xs-7">
                    {{ form.code }}
                    <span style="color: red;">{{ form.code.errors.0 }}</span>
                </div>
                <div class="col-xs-5">
                    <img id="image_code" src="/image/code" style="width: 125px;">
                </div>
            </div>
        </div>

 PS:点击图片验证码,进行刷新

 

 login.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <style>
        .account {
            width: 400px;
            border: 1px solid #dddddd;
            border-radius: 5px;
            box-shadow: 5px 5px 20px #aaa;

            margin-left: auto;
            margin-right: auto;
            margin-top: 100px;
            padding: 20px 40px;
        }

        .account h2 {
            margin-top: 10px;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="account">
    <h2>用户登录</h2>
    <form method="post" novalidate>
        {% csrf_token %}
        <div class="form-group">
            <label>用户名</label>
            {{ form.username }}
            <span style="color: red;">{{ form.username.errors.0 }}</span>
        </div>
        <div class="form-group">
            <label>密码</label>
            {{ form.password }}
            <span style="color: red;">{{ form.password.errors.0 }}</span>
        </div>
        <div class="form-group">
            <label for="id_code">图片验证码</label>
            <div class="row">
                <div class="col-xs-7">
                    {{ form.code }}
                    <span style="color: red;">{{ form.code.errors.0 }}</span>
                </div>
                <div class="col-xs-5">
                    {#                    点击图片,刷新图片#}
                    <img id="image_code" src="/image/code" style="width: 125px;" onclick="changeCodeImg()">
                </div>
            </div>
        </div>
        <input type="submit" value="登 录" class="btn btn-primary">
    </form>
</div>

<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
<script type="text/javascript">
    function changeCodeImg() {
         var num = Math.random() ;//生成一个随机数(防止缓存,刷新图片)
        $("#image_code").attr('src', "/image/code?num="+num);
    }
</script>

</body>
</html>

 

posted @ 2022-04-13 19:22  shuqi123  阅读(41)  评论(0)    收藏  举报