初识Django之验证码Pillow
为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能。
在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发,比如其中一个库Pillow。
安装Pillow
执行命令pip install pillow
Pillow
- Image画布
主要负责尺寸,颜色,模式 - ImageDraw画笔
属于哪个画布,主要负责文字,点,线,弧 - ImageFont字体
画布的辅助工具,负责字体和样式
绘制流程
- 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)
内存流
- 内存流BytesIO()
- 将图片存在内存流中,从流中获取到数据值
- 通过HttpResponse返回图片内容
- content_type
- MIME
- 表示打开数据的应用程序
- image/png
1 | # 字节流 |
完整代码如下:
- 在urls.py中添加
1
2
3urlpatterns = [
path('getcode/', views.get_code, name='get_code'),
] - 创建utils.py,写入数据处理的函数
1
2
3
4
5
6
7
8
9
10
11import random
def get_color():
return random.randrange(256)
def generate_code():
source = "1234567890qwertyuiopasdfghjklmnbvcxzZXCVBNMLKJHGFDSAQWERTYUIOP"
code = ""
for i in range(4):
code += random.choice(source)
return code - 在views.py
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
26
27
28
29def 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('Hiragino Sans GB.ttc', size=80)
# 随机字符
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(2000):
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")
验证码验证
- 客户端验证
- 服务端验证
- 在验证码生成时存储验证码
- 在提交时验证有效性
- 在login.html中加入验证码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</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="请输入验证码">
<img src="{% url 'app:get_code' %}" alt="验证码" >
<br>
<button>登陆</button>
</form>
</body>
</html> - 在views.py加入存储
1
2def get_code(request):
request.session['verify_code'] = verify_code - 登陆校验
比较存储的验证码和输入的验证码是否一致,这里利用lower()不区分大小写1
2
3
4
5
6
7
8
9
10
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("POST请求成功")
验证码刷新
- 浏览器缓存策略
- 以url为标识
- 解决方案
- 每次不同地址
- 对地址进行参数拼接不同参数
- 创建static文件夹,并在创建子文件夹js,创建login.js。这里用的是jquery写法。
1
2
3
4
5
6$(function () {
$("img").click(function () {
console.log("点到我了")
$(this).attr("src", '/app/getcode/?t=' + Math.random())
})
}) - 导入
1
2<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>
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 随心所欲录!
评论