实例:通过前台和后台,实现用户登录页面动态图片验证码校验,图片验证码部分使用Pillow模块实现,作为单独学习部分记录。

前端:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<link rel="stylesheet" href="/static/commons.css" />
</head>
<body>
<div>
<div>用户登录</div>
<form>
<div>
<label>用户名</label>
<input type="text" placeholder="请输入用户名" />
</div>
<div>
<label>密码</label>
<input type="text" placeholder="请输入密码" />
</div>
<div>
<label>验证码</label>
<div>
<input type="text" placeholder="输入验证码" name="check_code">
</div>
<div>
<img src="/app04/check_code.html" onclick="changeCheckCode(this);">
</div>
</div>
</form>
</div>
<script>
function changeCheckCode(ths) {
{# 可以简单实现验证码刷新#}
ths.src = ths.src + '?'
}
</script>
</body>
</html>

后台路由:

    url(r'^login',views.login),
url(r'^check_code.html',views.check_code),

后台views:

def check_code(request):
'''
验证码
:param request:
:return:
'''
from io import BytesIO
# 在内存创建文件
stream = BytesIO() # 调用自定义的check_code方法生成一个图片和一个验证码字串,check_code写法请参考验证码实例
img,code = create_validate_code()
# 将图片写入到内存中以图片形式
img.save(stream,'PNG')
# 为当前请求设置session
request.session['CheckCode'] = code
# stream.getvalue()是从内存中获取图片
return HttpResponse(stream.getvalue())
def login(request):
if request.method == 'POST':
if request.POST.get('check_code').upper() == request.session['CheckCode'].upper():
print('验证码正确')
else:
print('验证码错误') return render(request,'app04/login.html')

图片验证码实现模块学习记录

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)

三、滑动验证码应用

我们可以借助插件来做

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

2、筛选有用的路径

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

具体实现

1 #滑动验证码
2 url(r'^pc-geetest/register', pcgetcaptcha, name='pcgetcaptcha'),
3 url(r'^pc-geetest/ajax_validate', pcajax_validate, name='pcajax_validate'), 复制代码
1 # ================
2 from app01.geetest import GeetestLib
3 pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c"
4 pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4"
5 mobile_geetest_id = "7c25da6fe21944cfe507d2f9876775a9"
6 mobile_geetest_key = "f5883f4ee3bd4fa8caec67941de1b903"
7 # 滑动验证码
8 def pcgetcaptcha(request):
9 user_id = 'test'
10 gt = GeetestLib(pc_geetest_id, pc_geetest_key)
11 status = gt.pre_process(user_id)
12 request.session[gt.GT_STATUS_SESSION_KEY] = status
13 request.session["user_id"] = user_id
14 response_str = gt.get_response_str()
15 return HttpResponse(response_str)
16 # 滑动验证码
17 def pcajax_validate(request):
18
19 if request.method == "POST":
20 # 验证的验证码
21 ret = {"flag": False, "error_msg": None}
22 gt = GeetestLib(pc_geetest_id, pc_geetest_key)
23 challenge = request.POST.get(gt.FN_CHALLENGE, '')
24 validate = request.POST.get(gt.FN_VALIDATE, '')
25 seccode = request.POST.get(gt.FN_SECCODE, '')
26 status = request.session[gt.GT_STATUS_SESSION_KEY]
27 user_id = request.session["user_id"]
28 print("status",status)
29 if status:
30 result = gt.success_validate(challenge, validate, seccode, user_id)
31 else:
32 result = gt.failback_validate(challenge, validate, seccode)
33 if result: #如果验证验证码正确,就验证用户名是否正确
34 username = request.POST.get("username")
35 password = request.POST.get("password")
36
37 # 验证用户名和密码
38 user = auth.authenticate(username=username, password=password)
39 if user:
40 # 如果验证成功就让登录
41 ret["flag"] = True
42 auth.login(request, user)
43 else:
44 ret["error_msg"] = "用户名和密码错误"
45 else:
46 ret["error_msg"] = "验证码错误"
47 return HttpResponse(json.dumps(ret))
48 else:
49 return render(request, "login.html")
复制代码 复制代码
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width">
7 <title>Title</title>
8 <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
9 <link rel="stylesheet" href="/static/css/login.css">
10 <script src="/static/jquery-3.2.1.min.js"></script>
11 滑动验证码的时候导入
12 <script src="http://static.geetest.com/static/tools/gt.js"></script>
13 <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
14 <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
15
16 </head>
17 <body>
18 <div class="container">
19 <div class="row">
20 <div class="col-md-1=10">
21 <form class="form-horizontal" id="form_data" action="/login/" method="post">
22 {% csrf_token %}
23 <div class="form-group">
24 <label for="username" class="col-sm-2 control-label">用户名</label>
25 <div class="col-sm-5">
26 <input type="text" class="form-control" id="username" placeholder="username" name="username">
27 </div>
28 </div>
29 <div class="form-group">
30 <label for="password" class="col-sm-2 control-label">密码</label>
31 <div class="col-sm-5">
32 <input type="password" class="form-control" id="password" placeholder="password" name="password">
33 </div>
34 </div>
35 <div class="form-group">
36 <div class="row">
37 <div class="col-md-6 col-md-offset-1">
38 {# 文字部分#}
39 <label for="vialdCode" class="col-sm-2 control-label">验证码</label>
40 <div class="col-sm-5">
41 <input type="text" class="form-control vialdCode_text" id="vialdCode" placeholder="验证码" name="vialdCode">
42 </div>
43 {# 图片部分#}
44 <div class="col-md-5">
45 <img class="vialdCode_img" src="/get_vaildCode_img/" alt="" width="200px" height="100px">
46 {# <a href=""></a> #}
47 </div>
48 </div>
49
50 </div>
51 </div>
52 <div class="form-group">
53 <div class="col-sm-offset-2 col-sm-10">
54 <div class="checkbox">
55 <label>
56 <input type="checkbox"> 下次自动登录
57 </label>
58 </div>
59 </div>
60 </div>
61 <div class="form-group">
62 <div class="col-sm-offset-2 col-sm-10">
63 <p>
64 <button type="button" class="btn btn-success login" id="submit">登录</button>
65 <span class="error has-error"></span></p>
66 <p>
67 <button type="button" class="btn btn-primary register">注册</button>
68 </p>
69 </div>
70 <div id="popup-captcha"></div>
71 </div>
72 </form>
73 </div>
74 </div>
75 </div>
76 {#滑动验证码#}
77 <script>
78 var handlerPopup = function (captchaObj) {
79 $("#submit").click(function () {
80 captchaObj.show();
81 });
82 //定时函数
83 $(".login").click(function () {
84 function foo() {
85 $(".error").html("")
86 }
87
88 // 成功的回调
89 captchaObj.onSuccess(function () {
90 var validate = captchaObj.getValidate();
91 $.ajax({
92 url: "/pc-geetest/ajax_validate", // 进行二次验证
93 type: "post",
94 dataType: "json",
95 headers: {"X-CSRFToken": $.cookie('csrftoken')},
96 data: {
97 username: $('#username').val(),
98 password: $('#password').val(),
99 geetest_challenge: validate.geetest_challenge,
100 geetest_validate: validate.geetest_validate,
101 geetest_seccode: validate.geetest_seccode
102 },
103 success: function (data) {
104 console.log(data);
105 if (data["flag"]) {
106 {# alert(location.search);#}
107 {# alert(location.search.slice(6));#}
108 {# 方式一#}
109 {# if (location.search.slice(6)) {#}
110 {# 如果用户没有登录点赞的时候,当用户后来又登录了,就直接让跳转到当前点赞的那个路径#}
111 {# location.href = location.search.slice(6)#}
112 {# }#}
113 {# else {#}
114 {# window.location.href = '/index/'#}
115 {# }#}
116 {# 方式二:#}
117 alert($.cookie("next_path"));
118 if ($.cookie("next_path")){
119 location.href = $.cookie("next_path")
120 }
121 else{
122 location.href = "/index/"
123 }
124 }
125 else {
126 $(".error").html(data["error_msg"]);
127 setTimeout(foo, 3000)
128 }
129 }
130 });
131 });
132
133 });
134 // 将验证码加到id为captcha的元素里
135 captchaObj.appendTo("#popup-captcha");
136 // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html
137 };
138 // 验证开始需要向网站主后台获取id,challenge,success(是否启用failback)
139 $.ajax({
140 url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加随机数防止缓存
141 type: "get",
142 dataType: "json",
143 success: function (data) {
144 // 使用initGeetest接口
145 // 参数1:配置参数
146 // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件
147 initGeetest({
148 gt: data.gt,
149 challenge: data.challenge,
150 product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效
151 offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注
152 // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config
153 }, handlerPopup);
154 }
155 });
156 </script>

django学习之- 动态验证码学习的更多相关文章

  1. CgLib动态代理学习【Spring AOP基础之一】

    如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发 ...

  2. WPF-学习笔记 动态修改控件Margin的值

    原文:WPF-学习笔记 动态修改控件Margin的值 举例说明:动态添加一个TextBox到Grid中,并设置它的Margin: TextBox text = new TextBox(); t_gri ...

  3. Django之动态验证码的生成

    kind.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  4. Java学习之动态代理篇

    Java学习之动态代理篇 0x00 前言 在后面的漏洞研究的学习中,必须要会的几个知识点.反射机制和动态代理机制.至于反射的前面已经讲到过了,这里就不做更多的赘述了. 0x01 动态代理 这里先来讲一 ...

  5. ActiveMQ基本详解与总结& 消息队列-推/拉模式学习 & ActiveMQ及JMS学习

    转自:https://www.cnblogs.com/Survivalist/p/8094069.html ActiveMQ基本详解与总结 基本使用可以参考https://www.cnblogs.co ...

  6. java的动态验证码单线设计

    1.java的动态验证码我这里将介绍两种方法: 一:根据java本身提供的一种验证码的写法,这种呢只限于大家了解就可以了,因为java自带的模式编写的在实际开发中是没有意义的,所以只供学习一下就可以了 ...

  7. Django + Celery 实现动态配置定时任务

    哈喽,今天给大家分享一篇Django+Celery实现动态配置定时任务,因为最近也是无意间看到一位大佬关于这块的文章,然后自己觉得不错,也想学习写一下,然后最终实现功能是在前端页面统一管理计划任务,大 ...

  8. Vue学习笔记-vue-element-admin 前端学习

    一  使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7  (Windows x86- ...

  9. JavaWeb学习总结-04 Servlet 学习和使用

    一 Servlet 1 Servlet概念 Servlet时运行在服务器端的Java程序. Servlet的框架核心是 javax.servlet.Servlet 接口. 所有自定义的Servlet都 ...

随机推荐

  1. Android里的 ART、JIT、AOT、Dalvik之间有什么关系?

    ART.JIT.AOT.Dalvik之间有什么关系? JIT与Dalvik JIT是"Just In Time Compiler"的缩写,就是"即时编译技术", ...

  2. 使用Jenkins进行android项目的自动构建(6)

    之前已经介绍过使用Maven做构建,在来介绍一下Gralde的自动化构建. 什么是Gralde?官方的解释是 Gradle is an open source build automation sys ...

  3. Javascript异步编程的常用方法

    Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任 ...

  4. HDU 5414 CRB and String (字符串,模拟)

    题意:给两个字符串s和t,如果能插入一些字符使得s=t,则输出yes,否则输出no.插入规则:在s中选定一个字符c,可以在其后面插入一个字符k,只要k!=c即可. 思路:特殊的情况就是s和t的最长相同 ...

  5. DAX:New and returning customers

    The New and Returning Customers pattern dynamically calculates the number of customers with certain ...

  6. echart-柱状图

    目前在改别人遗留的bug,需求: 宽度 自适应的情况下 展示不友好:宽度太大 上下不居中 需求 要 上下 无论是否 有内容 都要居中展示 以0刻度为标准 宽度 设置 series: [ { name: ...

  7. function语句注意事项

    function语句 在Javascript中定义一个函数,有两种写法: function foo() { } 和 var foo = function () { } 两种写法完全等价.但是在解析的时 ...

  8. QT_7_资源文件_对话框_QMessageBox_界面布局_常用控件

    资源文件 1.1. 将资源导入到项目下 1.2. 添加文件—>Qt -->Qt Resource File 1.3. 起名称 res ,生成res.qrc文件 1.4. 右键 open i ...

  9. ERROR: HHH000091: Expected type: java.sql.Timestamp, actual value: java.lang.Integer

    在将MySql的数据对应到Java的实体类的时候, 遇到了错误 关键点: Hibernate从mysql数据库查出来的Timestamp类型的数据, 会被Hibernate(或者是数据库连接池Drui ...

  10. sed替换字符串中的某些字符

    test.txt原文内容 http://jsldfjaslfjsldfjasl/test?jlsdfjsalfjslfd 使用sed替换 sed -ri 's/(http:\/\/)[^\/]*(\/ ...