本文目录导读:

我来分享几种生成验证码的脚本方法,从简单到复杂都有:
Python + Pillow(最常用)
基础数字字母验证码
from PIL import Image, ImageDraw, ImageFont
import random
import string
def generate_captcha(width=200, height=80, length=4):
# 创建空白图片
image = Image.new('RGB', (width, height), (255, 255, 255))
draw = ImageDraw.Draw(image)
# 验证码字符
chars = string.ascii_uppercase + string.digits
captcha_text = ''.join(random.choice(chars) for _ in range(length))
# 绘制字符
for i, char in enumerate(captcha_text):
# 随机颜色
color = (random.randint(0, 150),
random.randint(0, 150),
random.randint(0, 150))
# 随机位置
x = 20 + i * 40
y = random.randint(10, 30)
# 绘制文本
draw.text((x, y), char, fill=color, font=None)
# 添加干扰线
for _ in range(5):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2),
fill=(random.randint(150, 255),)*3, width=2)
# 添加噪点
for _ in range(100):
x = random.randint(0, width)
y = random.randint(0, height)
draw.point((x, y), fill=(random.randint(0, 255),)*3)
return image, captcha_text
# 使用示例
image, text = generate_captcha()
image.save('captcha.png')
print(f"验证码: {text}")
带干扰线和扭曲的验证码
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
import string
def generate_complex_captcha():
# 图片大小
width, height = 200, 80
image = Image.new('RGB', (width, height), 'white')
draw = ImageDraw.Draw(image)
# 自定义字体(需要系统字体)
try:
font = ImageFont.truetype("arial.ttf", 36)
except:
font = ImageFont.load_default()
# 生成随机字符
chars = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
# 绘制字符并添加随机旋转
for i, char in enumerate(chars):
color = (random.randint(0, 100),
random.randint(0, 100),
random.randint(0, 100))
# 创建单个字符的临时图片
char_img = Image.new('RGB', (50, 50), 'white')
char_draw = ImageDraw.Draw(char_img)
char_draw.text((5, 5), char, fill=color, font=font)
# 随机旋转
angle = random.randint(-30, 30)
char_img = char_img.rotate(angle, expand=True)
# 粘贴到主图
position = (10 + i * 45, random.randint(5, 15))
image.paste(char_img, position)
# 添加背景干扰元素
for i in range(10):
draw.line(
[(random.randint(0, width), random.randint(0, height)),
(random.randint(0, width), random.randint(0, height))],
fill=(random.randint(150, 255),) * 3,
width=1
)
# 添加椭圆干扰
for i in range(3):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
draw.ellipse([x1, y1, x1+20, y1+15],
outline=(random.randint(100, 200),)*3)
return image, chars
# 生成并保存
image, code = generate_complex_captcha()
image.save('complex_captcha.png')
Node.js + canvas
const Canvas = require('canvas');
const { createCanvas } = Canvas;
function generateCaptcha() {
const width = 200;
const height = 80;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
// 背景
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, width, height);
// 生成随机字符
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
let captchaText = '';
for (let i = 0; i < 4; i++) {
captchaText += chars[Math.floor(Math.random() * chars.length)];
}
// 绘制字符
for (let i = 0; i < captchaText.length; i++) {
ctx.font = `${30 + Math.random() * 10}px Arial`;
ctx.fillStyle = `rgb(${Math.random()*100}, ${Math.random()*100}, ${Math.random()*100})`;
ctx.setTransform(
Math.cos(rotation), Math.sin(rotation),
-Math.sin(rotation), Math.cos(rotation),
x, y
);
ctx.fillText(captchaText[i], 20 + i * 40, 50);
}
// 添加干扰线
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.moveTo(Math.random() * width, Math.random() * height);
ctx.lineTo(Math.random() * width, Math.random() * height);
ctx.strokeStyle = `rgba(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 0.5)`;
ctx.stroke();
}
return {
image: canvas.toBuffer(),
text: captchaText
};
}
// 使用
const { image, text } = generateCaptcha();
require('fs').writeFileSync('captcha.png', image);
更安全的方案(带渐变和纹理)
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import numpy as np
import random
def generate_advanced_captcha():
width, height = 240, 80
image = Image.new('RGB', (width, height), 'white')
draw = ImageDraw.Draw(image)
# 渐变背景
for x in range(width):
for y in range(height):
# 创建渐变效果
r = int(200 + 55 * (x / width))
g = int(200 + 55 * (y / height))
b = int(200)
draw.point((x, y), fill=(r, g, b))
# 字符叠加
chars = ''.join(random.choices('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', k=4))
font = ImageFont.truetype("arial.ttf", 36)
for i, char in enumerate(chars):
# 创建字符层
char_layer = Image.new('RGBA', (60, 60), (0, 0, 0, 0))
char_draw = ImageDraw.Draw(char_layer)
char_draw.text((5, 5), char, font=font,
fill=(random.randint(0, 80),) * 3)
# 旋转和扭曲
char_layer = char_layer.rotate(random.randint(-25, 25),
reshape=True)
char_layer = char_layer.resize((45, 45))
# 合成
x = 10 + i * 55
y = 15 + random.randint(-5, 5)
image.paste(char_layer, (x, y), char_layer)
# 高斯模糊
image = image.filter(ImageFilter.GaussianBlur(0.5))
return image, chars
# 使用
image, code = generate_advanced_captcha()
image.save('advanced_captcha.png')
简单的PHP版本
<?php
function generateCaptcha($width = 200, $height = 80) {
// 创建图片
$image = imagecreatetruecolor($width, $height);
$bg_color = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $bg_color);
// 生成随机字符
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$captcha = '';
for ($i = 0; $i < 4; $i++) {
$captcha .= $chars[rand(0, strlen($chars) - 1)];
}
// 写入字符
for ($i = 0; $i < strlen($captcha); $i++) {
$color = imagecolorallocate($image,
rand(0, 100), rand(0, 100), rand(0, 100));
$angle = rand(-20, 20);
// 使用直线模拟字符
imagestring($image, 5, 20 + $i * 40, rand(10, 40),
$captcha[$i], $color);
}
// 添加干扰线
for ($i = 0; $i < 5; $i++) {
$color = imagecolorallocate($image,
rand(150, 200), rand(150, 200), rand(150, 200));
imageline($image, rand(0, $width), rand(0, $height),
rand(0, $width), rand(0, $height), $color);
}
// 输出
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
return $captcha;
}
// 调用
$code = generateCaptcha();
session_start();
$_SESSION['captcha'] = $code;
?>
使用建议
- 字符集:避免使用容易混淆的字符(如0和O,1和l)
- 复杂度:根据安全性需求调整干扰程度
- 存储:验证码需要与session关联,设置过期时间
- 可访问性:考虑提供语音验证码选项
- 安全性:存储MD5哈希值而非明文
选择哪种方案取决于你的技术栈和需求复杂度,如果需要更具体的实现细节,可以告诉我你的使用场景!