本篇文章主要讲实现验证码的原生方法,当然,在实际开发中,有很多插件可以实现验证码。

摘要

在用户登录,注册以及一些敏感操作的时候,我们为了防止服务器被暴力请求,或爬虫爬取,我们可以使用验证码进行过滤,减轻服务器的压力。

验证码需要使用绘图 Pillow

pip install Pillow

核心

Image,ImageDraw,ImageFont

绘制流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
background = (10,20,30)  RGB颜色

# 初始化画布

image = Image.new(‘RGB’,(100,50),background)

# 获取画布中画笔对象

draw = ImageDraw.Draw(image)

# 绘制验证码,随机四个

font = ImageFont.truetype(‘path’,size)

fontcolor = (20,40,60)

draw.text((x,y),’R’,font,fontcolor)

最后扫尾

1
2
3
4
5
6
7
8
9
10
del draw 

Import io

buf = io.BytesIO()

Image.save(buf,’png’)

return HttpResponse(buf.getvalue(),’image/png’)

实例

  • 对于功能性的函数,我们一般在app目录中建立utils.py文件,将功能函数或者与视图函数无关的函数放入

  • 如果想要自定义字体,可以在setting中添加FONT_PATH,把字体文件放入static/font中

步骤1

首先建立好两个视图函数,一个是生成验证码的,还有一个是验证是否成功的登录页面

具体步骤不在赘述,可以参看前面的文章。

步骤2

在utils.py文件中编写两个函数,一个用来生成随机RBG值,一个用来生成随机的验证码文字。

1
2
3
4
5
6
7
8
9
import random
def get_color():
return random.randrange(256)
def generate_code():
source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"
code = ""
for i in range(4):
code += random.choice(source)
return code

步骤3

在views中创建生成验证码的界面和包含验证码的登录界面

验证码生成函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def get_code(request):
# 初始化画布,初始化画笔
mode = "RGB"
size = (200, 100)
red = get_color()
green = get_color()
blue = get_color()
color_bg = (red, green, blue)
# 新建画布
image = Image.new(mode=mode, size=size, color=color_bg)
# 新建画笔
imagedraw = ImageDraw(image, mode=mode)
imagefont = ImageFont.truetype(settings.FONT_PATH, 100)
verify_code = generate_code()
request.session['verify_code'] = verify_code
for i in range(4):
fill = (get_color(), get_color(), get_color())
imagedraw.text(xy=(50*i, 0), text=verify_code[i], font=imagefont, fill=fill)
for i in range(10000):
fill = (get_color(), get_color(), get_color())
xy = (random.randrange(201), random.randrange(100))
imagedraw.point(xy=xy, fill=fill)
fp = BytesIO()# 添加二进制内存流
image.save(fp, "png")
return HttpResponse(fp.getvalue(), content_type="image/png")# 需要添加格式限定

登陆函数:

1
2
3
4
5
6
7
8
9
10
11
@csrf_exempt
def login(request):
if request.method == "GET":
return render(request, 'login.html')
elif request.method == "POST":
receive_code = request.POST.get("verify_code")
store_code = request.session.get("verify_code")

if receive_code.lower() != store_code.lower():
return redirect(reverse('app:login'))
return HttpResponse("登录成功")

步骤4

实现登陆界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.1/jquery.js"></script>
<script type="text/javascript" src="{% static 'js/login.js' %}"></script>
</head>
<body>
<form action="{% url 'app:login' %}" method="post">
<span>用户名:</span> <input type="text" name="username" placeholder="请输入用户名">
<br>
<span>验证码:</span><input type="text" name="verify_code" placeholder="请输入下图中的验证码">
<br>
<img src="{% url 'app:get_code' %}">
{# <img src="#">#}
<br>
<button>登录</button>
</form>
</body>
</html>

步骤5

实现登录界面中的js模块,添加点击验证码自动切换的功能

1
2
3
4
5
6
$(function () {
$("img").click(function () {
console.log("点到我了");
$(this).attr("src", "/app/getcode/?t=" + Math.random());
})
})

思维导图

8NIiRO.md.png