本文目录导读:

我来为你详细介绍一下图形验证码的生成方法,这通常包括前端展示和后端生成两个部分。
核心生成流程(后端)
最主流的方式是后端生成图片并返回,前端负责展示,流程如下:
- 生成随机字符串:生成一组随机的字母、数字或汉字。
- 存放到Session/Redis:将此字符串(原文)与当前用户的会话(Session)或临时缓存(如Redis,用于分布式系统)关联起来。
- 不存图片内容,只存文字:服务器生成图片后,通常只保存验证码的文字到内存中,用于后续校验,图片本身不保存。
- 绘制图片:用服务器端绘图库(如Java的
BufferedImage、Python的Pillow、PHP的GD库),在内存中绘制一张包含该字符串的图片,并加入干扰元素(线条、噪点、扭曲等)。 - 输出图片流:将生成的图片以字节流的形式输出到HTTP响应中,并设置响应头,让浏览器将其作为图片渲染。
- 前端展示:前端用一个
<img>标签或<canvas>,src指向后端生成验证码的API地址。
全代码示例(Python + Flask)
这是一个超简单的示例,用Python的Pillow和Flask实现。
安装依赖
pip install flask Pillow
核心代码
import random
import string
from io import BytesIO
from flask import Flask, session, make_response
from PIL import Image, ImageDraw, ImageFont
app = Flask(__name__)
app.secret_key = 'your_secret_key' # 必须要有密钥才能使用session
# 生成随机验证码文本
def generate_code(length=4):
# 移除容易混淆的字符如 1, l, 0, O
chars = string.ascii_uppercase + string.digits
chars = chars.replace('I', '').replace('L', '').replace('O', '').replace('0', '')
return ''.join(random.choices(chars, k=length))
# 生成验证码图片
def generate_image(code):
width, height = 120, 40
# 1. 创建画布(背景白色)
image = Image.new('RGB', (width, height), (255, 255, 255))
draw = ImageDraw.Draw(image)
# 2. 添加干扰点
for _ in range(100):
x, y = random.randint(0, width), random.randint(0, height)
draw.point((x, y), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
# 3. 添加干扰线
for _ in range(3):
x1, y1 = random.randint(0, width), random.randint(0, height)
x2, y2 = random.randint(0, width), random.randint(0, height)
draw.line([(x1, y1), (x2, y2)], fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
# 4. 绘制文字(使用默认字体)
font = ImageFont.load_default()
for i, char in enumerate(code):
# 每个字符随机偏移和旋转角度(简化版仅偏移)
x = 10 + i * 25 + random.randint(-5, 5)
y = random.randint(5, 15)
# 随机颜色
color = (random.randint(50, 200), random.randint(50, 200), random.randint(50, 200))
draw.text((x, y), char, font=font, fill=color)
# 5. 返回图片二进制流
buf = BytesIO()
image.save(buf, format='PNG')
buf.seek(0)
return buf
@app.route('/captcha')
def captcha():
# 1. 生成验证码文本
code = generate_code()
# 2. 存入Session(用于后续校验)
session['captcha_code'] = code
# 3. 生成图片
img_buf = generate_image(code)
# 4. 返回图片流
response = make_response(img_buf.getvalue())
response.content_type = 'image/png'
# 禁止缓存,确保每次请求都获取新验证码
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
return response
if __name__ == '__main__':
app.run(debug=True)
前端展示
<img src="/captcha" id="captcha_img" onclick="this.src='/captcha?'+Math.random()" />
点击图片时,会重新请求验证码(加随机数防止缓存)。
其他实现方式
纯前端生成(不推荐用于安全场景)
- Canvas + JS:在前端用JavaScript的Canvas API生成验证码图片。
- SVG:生成包含随机文字的SVG矢量图。
- 缺点:验证码文本暴露在前端JS代码中,很容易被破解,不能用于真正的安全验证,仅可用于防误触等低安全需求。
使用第三方验证码服务(推荐用于高安全场景)
对于重要业务(登录、支付),建议直接使用专业服务:
- Google reCAPTCHA:全球通用,用户体验好,点击“我不是机器人”即可。
- 阿里云/腾讯云的验证码服务:智能、安全,支持滑块、点选等。
- hCaptcha:reCAPTCHA的替代方案,注重隐私。
优点:AI难以破解,无需自己维护复杂的反破解逻辑。
常见的图形验证码形式
| 类型 | 描述 | 实现难度 | 安全性 |
|---|---|---|---|
| 数字+字母 | 经典的4-6位随机字符,加干扰线/噪点 | 低 | 低 |
| 汉字验证码 | 显示中文词语,用户输入 | 中(需中文字体) | 低 |
| 算术验证码 | 如“25 + 17 = ?” | 低 | 低 |
| 滑块验证码 | 拖动滑块到缺口位置 | 高(复杂前后端交互) | 高 |
| 点选验证码 | 按顺序点击图片中的指定物体 | 高(需要图库) | 高 |
安全与最佳实践
- 一次性使用:验证码校验成功或失败后,立刻从Session/Redis中删除,防止重复使用。
- 设置过期时间:验证码生成后,建议5分钟内有效,可以存入Redis并设置TTL。
- 防暴力破解:
- 限制请求频率:同一IP短时间内连续请求验证码超过阈值,暂时封禁。
- 增加复杂度:加大干扰、扭曲、噪点,让OCR难以识别。
- 区分大小写:为降低用户输入困难,建议不区分大小写,生成时统一转大写,校验时也转大写。
- 无状态Token化(推荐):在分布式系统中,Session可能不共享,建议:
- 生成验证码后将文本加密(或计算哈希),作为
captcha_token返回给前端。 - 前端提交时将
captcha_token和用户输入的验证码一起提交。 - 后端用同样的密钥解密或哈希比对,无需Session。
- 生成验证码后将文本加密(或计算哈希),作为
- 简单场景:使用后端绘图库(如Pillow、Java Graphics2D)生成简单的数字字母验证码,存Session。
- 生产环境:推荐使用第三方服务(reCAPTCHA等)或采用更复杂的滑块验证码,安全性高且维护成本低。
- 关键:不要在验证码生成逻辑中向任何人(包括前端)泄露正确的验证码文本。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播