用python实现一个简单的验证码


Posted in Python onDecember 09, 2020

我们经常在登录一个网站,或者注册的时候需要输入一个验证码,有时候觉得很烦,因为有些验证码不仅复杂还看不清,许多用户就会因为这些而懒得再登录或者注册之类的。
既然验证码会造成流失用户的风险,为什么大家都还要使用验证码呢?
这是验证码在一定程度上起到保护网站安全的作用,比如防止大规模恶意注册(比如手机验证码形式,一机一户),再比如反爬虫(至少不会轻易让你爬取数据)等,你看用户基数最大的12306,就会有各种验证码。
既然验证码这么重要,它的原理是什么?是怎么实现的?
它的原理其实很简单,就是在服务器端生成验证码,发送给客户端,并以图像格式显示。客户端提交所显示的验证码,服务端接收并进行比较,若比对失败则不能实现登录或注册,反之成功后跳转相应界面。

我们知道了其原理,实现起来就很简单了,现在网络上也有各种各样已经做好的验证码,我们完全可以拿来即用。但是为了更好的理解其原理,我们来手撸一个简单的验证码,以下是在Django中实现。

简单的验证码

(1)、我们在urls.py中定义一条路由,如下:

url(r'getcode', views.get_code, name="get_code"),

(2)、我们定义一个视图函数get_code(),如下:

from io import BytesIO

from PIL import Image, ImageDraw, ImageFont
from django.conf import settings
from django.shortcuts import render, HttpResponse, redirect
def get_code(request):
  """
  手撸一个验证码
  """
  # 定义图像颜色模型
  mode = "RGB"
  # 定义图像尺寸
  size = (200, 100)
  # 定义背景色
  bg_color = (255, 0, 0)
  # 创建图像
  image = Image.new(mode=mode, size=size, color=bg_color)
  # 创建画布
  image_draw = ImageDraw.Draw(image, mode=mode)
  # 创建字体,第一个参数是字体,第二个参数是字体大小
  image_font = ImageFont.truetype(settings.FONT_PATH, 100)
  # 创建一个验证码
  verify_code = "Joke"
  # 生成验证码
  fill_color = (255,255,255)
  for i in range(4):
    image_draw.text(xy=(50 * i, 0), text=verify_code[i], font=image_font, fill=fill_color)
  # 保存图像
  fp = BytesIO()
  image.save(fp, "png")
  return HttpResponse(fp.getvalue(), content_type="image/png")

其中settings.FONT_PATH是我预先定义好的字段,如下

STATICFILES_DIRS = [  os.path.join(BASE_DIR, "statics"),]
FONT_PATH = os.path.join(os.path.join(STATICFILES_DIRS[0], "fonts"),"constan.ttf")

然后我们我们启动服务python manager.py runserver,在浏览器上就可以看到验证码生成了

用python实现一个简单的验证码

能是实现了,但是我们现在是自定义了一个验证码字段,我们是需要随机生成验证码,而且字体颜色,背景颜色这些也不要定死了,然后我们再生成一些干扰点,我们对代码进行如下重构:

def get_code(request):
  """
  手撸一个验证码
  """
  # 定义图像颜色模型
  mode = "RGB"
  # 定义图像尺寸
  size = (200, 100)
  # 定义背景色
  bg_color = (get_color(), get_color(), get_color())
  # 创建图像
  image = Image.new(mode=mode, size=size, color=bg_color)
  # 创建画布
  image_draw = ImageDraw.Draw(image, mode=mode)
  # 创建字体,第一个参数是字体,第二个参数是字体大小
  image_font = ImageFont.truetype(settings.FONT_PATH, 100)
  # 创建一个验证码
  # verify_code = "Joke"
  verify_code = get_verify_code()
  # 生成验证码
  # fill_color = (255,255,255)
  for i in range(4):
    fill_color = (get_color(),get_color(),get_color())
    image_draw.text(xy=(50 * i, 0), text=verify_code[i], font=image_font, fill=fill_color)
  # 加入干扰点
  for i in range(10000):
    fill_color = (get_color(),get_color(),get_color())
    xy = (random.randrange(200), random.randrange(100))
    image_draw.point(xy=xy,fill=fill_color)
  # 保存图像
  fp = BytesIO()
  image.save(fp, "png")
  return HttpResponse(fp.getvalue(), content_type="image/png")


def get_color():
  """随机获取颜色"""
  return random.randrange(256)


def get_verify_code():
  """随机获取验证码"""
  verify_code = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for x in range(4))
  return verify_code

然后我们重启应用,刷新页面如下

用python实现一个简单的验证码

是不是有点神似了?下面我们创建一个简单的login页面,来实际应用一下验证码。

简单的登录页面

(1)、创建一个路由

url(r'login',views.login, name="login"),

(2)、创建一个Login的视图函数

def login(request):
  """登录页面"""
  if request.method == "POST":
    pass
  return render(request, "login.html")

(3)、创建一个login.html的template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Login</title>
</head>
<body>
<form action="{% url 'app01:login' %}" method="post">
	{% csrf_token %}
  <span>用户名:</span><input type="text" name="username">
  <br>
  <span>验证码:</span><input type="text" name="verify_code">
  <br>
  <img src="{% url 'app01:get_code' %}" alt="">
  <br>
  <button>登录</button>
</form>

</body>
</html>

然后重启服务,浏览器访问如下

用python实现一个简单的验证码

现在我们只是简单的搭建起了流程,我们需要的功能还没有实现,我们需要的功能有:
1、验证码校验
2、点击图片自动刷新验证码
3、忽略大小写

我们现在对项目进行重构,如下:
(1)、我们在get_code视图函数添加一行代码,如下

# 创建一个验证码
  # verify_code = "Joke"
  verify_code = get_verify_code()
# 加入session
  request.session['verify_code'] = verify_code
  ......

(2)、修改login视图函数,如下

def login(request):
  """登录页面"""
  if request.method == "POST":
    storage_code = request.session.get("verify_code")
    submit_code = request.POST.get("verify_code")
    if storage_code.lower() == submit_code.lower():
      return HttpResponse("登录成功")
  return render(request, "login.html")

(3)、修改login.html代码如下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Login</title>
</head>
<body>
<form action="{% url 'app01:login' %}" method="post">
  {% csrf_token %}
  <span>用户名:</span><input type="text" name="username">
  <br>
  <span>验证码:</span><input type="text" name="verify_code">
  <br>
  <img src="{% url 'app01:get_code' %}" alt="" name="verify_image">
  <br>
  <button>登录</button>
</form>
<script src="https://cdn.bootcss.com/jquery/3.2.0/jquery.js"></script>
<script>
  $(function () {
    $("img").on("click", function () {
      console.log("来了啊")
      $(this).attr("src","{% url 'app01:get_code' %}"+"?id="+Math.random())
    })
  })
</script>
</body>
</html>

然后就可以愉快的玩耍了,是不是很简单呢?

以上就是用python实现一个简单的验证码的详细内容,更多关于python 实现验证码的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
详解Python的Django框架中的模版相关知识
Jul 15 Python
使用Python脚本生成随机IP的简单方法
Jul 30 Python
Java Web开发过程中登陆模块的验证码的实现方式总结
May 25 Python
Python深入06——python的内存管理详解
Dec 07 Python
python读取csv文件并把文件放入一个list中的实例讲解
Apr 27 Python
解决python xx.py文件点击完之后一闪而过的问题
Jun 24 Python
如何利用Pyecharts可视化微信好友
Jul 04 Python
使用Python爬虫库requests发送表单数据和JSON数据
Jan 25 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
Apr 12 Python
深入了解NumPy 高级索引
Jul 24 Python
Python 实现RSA加解密文本文件
Dec 30 Python
python爬不同图片分别保存在不同文件夹中的实现
Apr 02 Python
使用Python提取文本中含有特定字符串的方法示例
Dec 09 #Python
python使用正则表达式匹配txt特定字符串(有换行)
Dec 09 #Python
PyTorch中clone()、detach()及相关扩展详解
Dec 09 #Python
python调用jenkinsAPI构建jenkins,并传递参数的示例
Dec 09 #Python
python excel多行合并的方法
Dec 09 #Python
PyTorch中的拷贝与就地操作详解
Dec 09 #Python
python 调用Google翻译接口的方法
Dec 09 #Python
You might like
15种PHP Encoder的比较
2007/03/06 PHP
PHP永久登录、记住我功能实现方法和安全做法
2015/04/27 PHP
php析构函数的简单使用说明
2015/08/24 PHP
PHP中对数组的一些常用的增、删、插操作函数总结
2015/11/27 PHP
PHP读取大文件的多种方法介绍
2016/04/04 PHP
php使用CURL模拟GET与POST向微信接口提交及获取数据的方法
2016/09/23 PHP
通过Mootools 1.2来操纵HTML DOM元素
2009/09/15 Javascript
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
说说JSON和JSONP 也许你会豁然开朗
2012/09/02 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
JavaScript实现彩虹文字效果的方法
2015/04/16 Javascript
基于insertBefore制作简单的循环插空效果
2015/09/21 Javascript
js实现页面跳转的五种方法推荐
2016/03/10 Javascript
dul无法加载bootstrap实现unload table/user恢复
2016/09/29 Javascript
iscroll动态加载数据完美解决方法
2017/07/18 Javascript
JavaScript JMap类定义与使用方法示例
2019/01/22 Javascript
详解vue配置后台接口方式
2019/03/29 Javascript
前端面试知识点目录一览
2019/04/15 Javascript
小程序多图列表实现性能优化的方法步骤
2019/05/28 Javascript
使用layui+ajax实现简单的菜单权限管理及排序的方法
2019/09/10 Javascript
深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)
2020/02/19 Javascript
vue组件入门知识全梳理
2020/09/21 Javascript
Python的加密模块md5、sha、crypt使用实例
2014/09/28 Python
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
python 脚本生成随机 字母 + 数字密码功能
2018/05/26 Python
Python3爬取英雄联盟英雄皮肤大图实例代码
2018/11/14 Python
pandas读取CSV文件时查看修改各列的数据类型格式
2019/07/07 Python
pycharm sciview的图片另存为操作
2020/06/01 Python
Ellos瑞典官网:北欧地区时尚、美容和住宅领域领先的电子商务网站
2019/11/21 全球购物
《他得的红圈圈最多》教学反思
2014/04/24 职场文书
2014年销售内勤工作总结
2014/12/01 职场文书
门店店长岗位职责
2015/04/14 职场文书
商务信函英语问候语
2015/11/10 职场文书
Mysql数据库按时间点恢复实战记录
2021/06/30 MySQL
试了下Golang实现try catch的方法
2021/07/01 Golang
Win11右下角图标点了没反应怎么办?Win11点击右下角图标无反应解决方法汇总
2022/07/07 数码科技