我们经常在登录一个网站,或者注册的时候需要输入一个验证码,有时候觉得很烦,因为有些验证码不仅复杂还看不清,许多用户就会因为这些而懒得再登录或者注册之类的。
既然验证码会造成流失用户的风险,为什么大家都还要使用验证码呢?
这是验证码在一定程度上起到保护网站安全的作用,比如防止大规模恶意注册(比如手机验证码形式,一机一户),再比如反爬虫(至少不会轻易让你爬取数据)等,你看用户基数最大的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,在浏览器上就可以看到验证码生成了
能是实现了,但是我们现在是自定义了一个验证码字段,我们是需要随机生成验证码,而且字体颜色,背景颜色这些也不要定死了,然后我们再生成一些干扰点,我们对代码进行如下重构:
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
然后我们重启应用,刷新页面如下
是不是有点神似了?下面我们创建一个简单的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="/UploadFiles/2021-04-08/{% url 'app01:get_code' %}">然后重启服务,浏览器访问如下
现在我们只是简单的搭建起了流程,我们需要的功能还没有实现,我们需要的功能有:
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="/UploadFiles/2021-04-08/{% url 'app01:get_code' %}">然后就可以愉快的玩耍了,是不是很简单呢?
以上就是用python实现一个简单的验证码的详细内容,更多关于python 实现验证码的资料请关注其它相关文章!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- [音展纪念碟]2006年《TAA台湾第十六届国际HI-ENDHI-FI音响展》2cd[WAV]
- 中国音乐地图之听见西藏山歌牧歌酒歌2020[WAV分轨]
- 王宏伟2017-永远的红飘带[太平洋影音][WAV+CUE]
- 费翔.1997-NOW现在【第一中国】【WAV+CUE】
- 新格合唱团.1981-我唱你和2辑(滚石新格民歌系列)【新格】【WAV+CUE】
- 陈柏宇.2011-QUINQUENNIUM【SONY】【WAV+CUE】
- 雨果唱片-《金唛系列-蔷薇依韵琼瑶》WAV
- 陈百强《凝望(2012华纳LPCD45限量版)[DMI]》[WAV整轨]
- 模拟之声慢刻CD《徐小凤45周年》[德国母带][低速原抓WAV+CUE]
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- 《王菲 单曲合集》[FlAC/分轨][520MB]
- 《费玉清 原味再现 水长流》[WAV+CUE][430MB]
- 群星.1992-畅销榜老歌金曲10CD【风格】【WAV+CUE】
- 孙悦.2024-时光音乐会【金蜂】【WAV+CUE】