网页验证码的作用
验证码的用途、常见类型及前端实现方式
问题
网页验证码有什么作用?常见的验证码类型有哪些?
解答
验证码的作用
验证码(CAPTCHA)的主要目的是区分人类用户和自动化程序(机器人),防止恶意行为。
具体作用:
- 防止暴力破解 - 阻止自动化程序尝试大量密码组合
- 防止垃圾注册 - 避免批量创建虚假账号
- 防止刷票/刷单 - 阻止自动化投票或下单
- 防止爬虫抓取 - 保护网站数据不被批量采集
- 防止接口滥用 - 限制短信、邮件等接口被恶意调用
常见验证码类型
| 类型 | 描述 | 安全性 |
|---|---|---|
| 图形验证码 | 识别扭曲的字母数字 | 低 |
| 计算验证码 | 简单数学运算 | 低 |
| 滑动验证码 | 拖动滑块到指定位置 | 中 |
| 点选验证码 | 按顺序点击指定文字/图片 | 中 |
| 行为验证码 | 分析鼠标轨迹等行为 | 高 |
| 短信/邮箱验证码 | 发送一次性验证码 | 高 |
前端实现示例
简单图形验证码
// 生成随机验证码
function generateCode(length = 4) {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789'
let code = ''
for (let i = 0; i < length; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length))
}
return code
}
// 绘制验证码到 Canvas
function drawCaptcha(canvas, code) {
const ctx = canvas.getContext('2d')
const width = canvas.width
const height = canvas.height
// 背景
ctx.fillStyle = '#f0f0f0'
ctx.fillRect(0, 0, width, height)
// 干扰线
for (let i = 0; i < 4; i++) {
ctx.strokeStyle = randomColor(150, 200)
ctx.beginPath()
ctx.moveTo(Math.random() * width, Math.random() * height)
ctx.lineTo(Math.random() * width, Math.random() * height)
ctx.stroke()
}
// 绘制文字
ctx.font = 'bold 30px Arial'
ctx.textBaseline = 'middle'
for (let i = 0; i < code.length; i++) {
ctx.fillStyle = randomColor(50, 150)
ctx.save()
ctx.translate(20 + i * 25, height / 2)
ctx.rotate((Math.random() - 0.5) * 0.4) // 随机旋转
ctx.fillText(code[i], 0, 0)
ctx.restore()
}
// 干扰点
for (let i = 0; i < 30; i++) {
ctx.fillStyle = randomColor(100, 200)
ctx.beginPath()
ctx.arc(Math.random() * width, Math.random() * height, 1, 0, Math.PI * 2)
ctx.fill()
}
}
// 生成随机颜色
function randomColor(min, max) {
const r = Math.floor(Math.random() * (max - min) + min)
const g = Math.floor(Math.random() * (max - min) + min)
const b = Math.floor(Math.random() * (max - min) + min)
return `rgb(${r},${g},${b})`
}
使用示例
<canvas id="captcha" width="120" height="40"></canvas>
<input type="text" id="input" placeholder="请输入验证码" />
<button id="refresh">刷新</button>
<button id="verify">验证</button>
<script>
let currentCode = ''
const canvas = document.getElementById('captcha')
function refresh() {
currentCode = generateCode()
drawCaptcha(canvas, currentCode)
}
document.getElementById('refresh').onclick = refresh
document.getElementById('verify').onclick = () => {
const input = document.getElementById('input').value
if (input.toLowerCase() === currentCode.toLowerCase()) {
alert('验证成功')
} else {
alert('验证失败')
refresh()
}
}
refresh() // 初始化
</script>
安全注意事项
// ❌ 错误:前端生成并验证(不安全)
if (userInput === frontendCode) {
submit()
}
// ✅ 正确:后端生成并验证
async function verify(userInput) {
const res = await fetch('/api/verify-captcha', {
method: 'POST',
body: JSON.stringify({ code: userInput, sessionId })
})
return res.json()
}
关键点
- 验证码用于区分人类和机器,防止自动化攻击
- 前端验证码仅用于展示,真正的验证必须在后端完成
- 图形验证码安全性较低,重要场景应使用行为验证或短信验证
- 验证码应有过期时间和错误次数限制
- 需要在用户体验和安全性之间取得平衡
目录