js验证码实现
验证码的基本原理
验证码(CAPTCHA)用于区分人类用户和自动化程序。常见类型包括图形验证码、滑动验证码、短信验证码等。JavaScript 可用于前端验证码的生成和验证逻辑。
图形验证码实现
使用 Canvas 生成随机字符验证码:
function generateCaptcha() {
const canvas = document.getElementById('captchaCanvas');
const ctx = canvas.getContext('2d');
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
let captcha = '';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < 6; i++) {
const char = chars.charAt(Math.floor(Math.random() * chars.length));
captcha += char;
ctx.font = '30px Arial';
ctx.fillStyle = getRandomColor();
ctx.fillText(char, 10 + i * 25, 30);
}
// 添加干扰线
for (let i = 0; i < 5; i++) {
ctx.strokeStyle = getRandomColor();
ctx.beginPath();
ctx.moveTo(Math.random() * canvas.width, Math.random() * canvas.height);
ctx.lineTo(Math.random() * canvas.width, Math.random() * canvas.height);
ctx.stroke();
}
return captcha;
}
function getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
验证逻辑处理
在表单提交时验证用户输入:
let currentCaptcha = generateCaptcha();
document.getElementById('refreshCaptcha').addEventListener('click', function() {
currentCaptcha = generateCaptcha();
});
document.getElementById('submitForm').addEventListener('submit', function(e) {
e.preventDefault();
const userInput = document.getElementById('captchaInput').value;
if (userInput.toUpperCase() === currentCaptcha) {
alert('验证码正确');
// 继续表单提交
} else {
alert('验证码错误');
currentCaptcha = generateCaptcha();
}
});
滑动验证码实现
基本滑动验证码的 HTML 结构:
<div class="slider-container">
<div class="slider-bg"></div>
<div class="slider-btn" draggable="true"></div>
</div>
JavaScript 拖动逻辑:
const sliderBtn = document.querySelector('.slider-btn');
let isDragging = false;
sliderBtn.addEventListener('mousedown', function(e) {
isDragging = true;
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
const container = document.querySelector('.slider-container');
const containerRect = container.getBoundingClientRect();
let newPosition = e.clientX - containerRect.left;
// 限制滑块在容器内移动
newPosition = Math.max(0, Math.min(newPosition, containerRect.width - sliderBtn.offsetWidth));
sliderBtn.style.left = newPosition + 'px';
});
document.addEventListener('mouseup', function(e) {
if (!isDragging) return;
isDragging = false;
// 验证是否滑动到指定位置(如右侧80%区域)
const container = document.querySelector('.slider-container');
const containerWidth = container.offsetWidth;
const btnPosition = parseInt(sliderBtn.style.left || 0);
if (btnPosition > containerWidth * 0.8) {
alert('验证成功');
} else {
sliderBtn.style.left = '0';
}
});
短信验证码倒计时
发送短信验证码时的倒计时功能:
function startCountdown(seconds) {
const btn = document.getElementById('sendSmsBtn');
let remaining = seconds;
btn.disabled = true;
btn.textContent = `重新发送(${remaining}s)`;
const timer = setInterval(() => {
remaining--;
btn.textContent = `重新发送(${remaining}s)`;
if (remaining <= 0) {
clearInterval(timer);
btn.disabled = false;
btn.textContent = '发送验证码';
}
}, 1000);
}
document.getElementById('sendSmsBtn').addEventListener('click', function() {
// 模拟发送验证码
startCountdown(60);
});
安全注意事项
前端验证码只能作为辅助验证,服务端必须进行二次验证。验证码生成逻辑应包含:
- 随机性足够强(避免简单数学运算)
- 会话绑定(每个验证码对应特定会话)
- 有效期限制(通常3-5分钟)
- 尝试次数限制(防止暴力破解)
服务端验证示例(Node.js):
const sessionCaptchas = {};
// 生成验证码时存储
app.post('/api/captcha/generate', (req, res) => {
const captcha = generateRandomString();
const sessionId = req.session.id;
sessionCaptchas[sessionId] = {
code: captcha,
expires: Date.now() + 300000 // 5分钟后过期
};
res.json({ captchaImage: generateImage(captcha) });
});
// 验证验证码
app.post('/api/captcha/verify', (req, res) => {
const { input, sessionId } = req.body;
const record = sessionCaptchas[sessionId];
if (!record || record.expires < Date.now()) {
return res.status(400).json({ error: '验证码已过期' });
}
if (input.toUpperCase() !== record.code) {
return res.status(400).json({ error: '验证码错误' });
}
delete sessionCaptchas[sessionId];
res.json({ success: true });
});





