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

作者:极客运维圈 时间:2023-05-23 12:07:58 

目录
  • 简单的验证码

  • 简单的登录页面

我们经常在登录一个网站,或者注册的时候需要输入一个验证码,有时候觉得很烦,因为有些验证码不仅复杂还看不清,许多用户就会因为这些而懒得再登录或者注册之类的。
既然验证码会造成流失用户的风险,为什么大家都还要使用验证码呢?
这是验证码在一定程度上起到保护网站安全的作用,比如防止大规模恶意注册(比如手机验证码形式,一机一户),再比如反爬虫(至少不会轻易让你爬取数据)等,你看用户基数最大的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>

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

来源:https://www.cnblogs.com/coolops/p/13577577.html

标签:python,验证码
0
投稿

猜你喜欢

  • Python jiaba库的使用详解

    2022-05-11 22:20:46
  • python代码实现五子棋游戏

    2021-04-18 01:20:48
  • MyBatis实现MySQL批量插入的示例代码

    2024-01-14 01:48:23
  • mysql中#{}和${}的区别详解

    2024-01-12 21:37:17
  • C#自动创建数据库实现代码

    2024-01-17 14:18:03
  • windows下重置mysql的root密码方法介绍

    2024-01-17 18:37:35
  • SQL 分布式查询、插入递增列示例

    2024-01-21 01:49:39
  • pandas Dataframe实现批量修改值的方法

    2022-12-19 21:52:59
  • Windows下使Python2.x版本的解释器与3.x共存的方法

    2021-03-14 22:22:17
  • 完美解决phpstudy安装后mysql无法启动(无需删除原数据库,无需更改任何配置,无需更改端口)直接共存

    2023-11-14 17:39:47
  • 解决os.path.isdir() 判断文件夹却返回false的问题

    2022-11-07 18:11:37
  • 利用CSS改善网站可访问性

    2010-10-20 20:12:00
  • python实现TF-IDF算法解析

    2021-06-02 03:27:51
  • python使用pygame实现笑脸乒乓球弹珠球游戏

    2021-07-26 09:49:47
  • python操作微信自动发消息的实现(微信聊天机器人)

    2021-01-06 23:22:24
  • 如何使用Typora+MinIO+Python代码打造舒适协作环境

    2023-11-12 15:12:10
  • windows下mysql 8.0.12安装步骤及基本使用教程

    2024-01-19 15:17:53
  • Python socket实现多对多全双工通信的方法

    2023-05-02 17:31:38
  • django rest framework 数据的查找、过滤、排序的示例

    2023-07-18 16:33:39
  • 对Django中static(静态)文件详解以及{% static %}标签的使用方法

    2021-03-27 20:28:21
  • asp之家 网络编程 m.aspxhome.com