网页验证码的作用

验证码的用途、常见类型及前端实现方式

问题

网页验证码有什么作用?常见的验证码类型有哪些?

解答

验证码的作用

验证码(CAPTCHA)的主要目的是区分人类用户和自动化程序(机器人),防止恶意行为。

具体作用:

  1. 防止暴力破解 - 阻止自动化程序尝试大量密码组合
  2. 防止垃圾注册 - 避免批量创建虚假账号
  3. 防止刷票/刷单 - 阻止自动化投票或下单
  4. 防止爬虫抓取 - 保护网站数据不被批量采集
  5. 防止接口滥用 - 限制短信、邮件等接口被恶意调用

常见验证码类型

类型描述安全性
图形验证码识别扭曲的字母数字
计算验证码简单数学运算
滑动验证码拖动滑块到指定位置
点选验证码按顺序点击指定文字/图片
行为验证码分析鼠标轨迹等行为
短信/邮箱验证码发送一次性验证码

前端实现示例

简单图形验证码

// 生成随机验证码
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()
}

关键点

  • 验证码用于区分人类和机器,防止自动化攻击
  • 前端验证码仅用于展示,真正的验证必须在后端完成
  • 图形验证码安全性较低,重要场景应使用行为验证或短信验证
  • 验证码应有过期时间和错误次数限制
  • 需要在用户体验和安全性之间取得平衡