🚀 增强验证码安全性和防刷机制
- 添加验证码请求限流器(30次/10分钟,超限封锁30分钟) - 添加验证码请求间隔控制(最小3秒间隔) - 升级验证码复杂度:4位数字 → 6位字母数字混合 - 移除易混淆字符(I/l/O/0/1等) - 优化验证码显示参数(尺寸、干扰线等) 这些改进大幅提升了验证码的安全性,有效防止暴力破解和恶意刷新。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -436,6 +436,46 @@ const shareLimiter = new RateLimiter({
|
|||||||
blockDuration: 20 * 60 * 1000
|
blockDuration: 20 * 60 * 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 创建验证码获取限流器(30次请求/10分钟,封锁30分钟)
|
||||||
|
const captchaLimiter = new RateLimiter({
|
||||||
|
maxAttempts: 30,
|
||||||
|
windowMs: 10 * 60 * 1000,
|
||||||
|
blockDuration: 30 * 60 * 1000
|
||||||
|
});
|
||||||
|
|
||||||
|
// 验证码最小请求间隔控制
|
||||||
|
const CAPTCHA_MIN_INTERVAL = 3000; // 3秒
|
||||||
|
const captchaLastRequest = new TTLCache(15 * 60 * 1000); // 15分钟自动清理
|
||||||
|
|
||||||
|
// 验证码防刷中间件
|
||||||
|
function captchaRateLimitMiddleware(req, res, next) {
|
||||||
|
const clientKey = `captcha:${captchaLimiter.getClientKey(req)}`;
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
// 最小时间间隔限制
|
||||||
|
const lastRequest = captchaLastRequest.get(clientKey);
|
||||||
|
if (lastRequest && (now - lastRequest) < CAPTCHA_MIN_INTERVAL) {
|
||||||
|
return res.status(429).json({
|
||||||
|
success: false,
|
||||||
|
message: '验证码请求过于频繁,请稍后再试'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
captchaLastRequest.set(clientKey, now, 15 * 60 * 1000);
|
||||||
|
|
||||||
|
// 窗口内总次数限流
|
||||||
|
const result = captchaLimiter.recordFailure(clientKey);
|
||||||
|
if (result.blocked) {
|
||||||
|
return res.status(429).json({
|
||||||
|
success: false,
|
||||||
|
message: `验证码请求过多,请在 ${result.waitMinutes} 分钟后再试`,
|
||||||
|
blocked: true,
|
||||||
|
resetTime: result.resetTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
// 登录防爆破中间件
|
// 登录防爆破中间件
|
||||||
function loginRateLimitMiddleware(req, res, next) {
|
function loginRateLimitMiddleware(req, res, next) {
|
||||||
const clientIP = loginLimiter.getClientKey(req);
|
const clientIP = loginLimiter.getClientKey(req);
|
||||||
@@ -601,17 +641,17 @@ app.get('/api/health', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 生成验证码API
|
// 生成验证码API
|
||||||
app.get('/api/captcha', (req, res) => {
|
app.get('/api/captcha', captchaRateLimitMiddleware, (req, res) => {
|
||||||
try {
|
try {
|
||||||
const captcha = svgCaptcha.create({
|
const captcha = svgCaptcha.create({
|
||||||
size: 4, // 验证码长度
|
size: 6, // 验证码长度
|
||||||
noise: 2, // 干扰线条数
|
noise: 3, // 干扰线条数
|
||||||
color: true, // 使用彩色
|
color: true, // 使用彩色
|
||||||
background: '#f0f0f0', // 背景色
|
background: '#f7f7f7', // 背景色
|
||||||
width: 120,
|
width: 140,
|
||||||
height: 40,
|
height: 44,
|
||||||
fontSize: 50,
|
fontSize: 52,
|
||||||
charPreset: '0123456789' // 只使用数字
|
charPreset: 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' // 去掉易混淆字符,字母+数字
|
||||||
});
|
});
|
||||||
|
|
||||||
// 将验证码文本存储在session中
|
// 将验证码文本存储在session中
|
||||||
|
|||||||
Reference in New Issue
Block a user