目录

防止手机验证码被刷React-TypeScript-与-Node.js-Express-的全面防御策略

防止手机验证码被刷:React + TypeScript 与 Node.js + Express 的全面防御策略

防止手机验证码被刷是开发中常见的安全问题,尤其是在涉及用户注册、登录或敏感操作时。攻击者可能会通过自动化脚本频繁请求验证码,导致短信轰炸或资源浪费。以下是如何在 React + TypeScript 前端和 Node.js + Express 后端中防止验证码被刷的深度分析,并结合代码实现。


1 常见的攻击场景

  1. 短信轰炸
  • 攻击者通过脚本频繁请求验证码,导致用户手机收到大量短信。
  1. 验证码滥用
  • 攻击者通过暴力破解或重放攻击,尝试破解验证码。
  1. 资源耗尽
  • 频繁请求验证码可能导致服务器资源耗尽,影响正常用户。

2 防御措施

2.1 前端防御措施

  1. 增加图形验证码
  • 在发送短信验证码之前,要求用户输入图形验证码,防止自动化脚本。
  1. 请求频率限制
  • 在前端限制用户点击“发送验证码”按钮的频率(如 60 秒内只能点击一次)。
  1. IP 和设备指纹识别
  • 记录用户 IP 和设备信息,用于后端分析和限制。

2.2 后端防御措施

  1. 请求频率限制
  • 使用 Redis 或内存缓存记录每个手机号或 IP 的请求频率,限制单位时间内的请求次数。
  1. 验证码有效期
  • 设置验证码的较短有效期(如 5 分钟),减少被滥用的风险。
  1. 验证码使用次数限制
  • 每个验证码只能使用一次,使用后立即失效。
  1. 黑名单机制
  • 将频繁请求验证码的 IP 或手机号加入黑名单,暂时禁止其请求。
  1. 日志监控
  • 记录验证码请求日志,监控异常行为。

3 前端实现(React + TypeScript)

3.1 增加图形验证码

在发送短信验证码之前,要求用户输入图形验证码。 import React, { useState } from ‘react’; import axios from ‘axios’; const SmsVerification: React.FC = () => { const [phone, setPhone] = useState(’’); const [captcha, setCaptcha] = useState(’’); const [isLoading, setIsLoading] = useState(false); const handleSendCode = async () => { if (!captcha) { alert(‘请输入图形验证码’); return; } setIsLoading(true); try { await axios.post(’/api/send-sms’, { phone, captcha }); alert(‘验证码已发送’); } catch (error) { alert(‘发送验证码失败’); } finally { setIsLoading(false); } }; return (

setPhone(e.target.value)} /> setCaptcha(e.target.value)} /> {isLoading ? ‘发送中…’ : ‘发送验证码’}

); }; export default SmsVerification;


3.2 请求频率限制

在前端限制用户点击“发送验证码”按钮的频率。 import React, { useState, useEffect } from ‘react’; const SmsVerification: React.FC = () => { const [countdown, setCountdown] = useState(0); const handleSendCode = () => { // 设置倒计时 60 秒 setCountdown(60); // 发送验证码逻辑… }; useEffect(() => { if (countdown > 0) { const timer = setTimeout(() => setCountdown(countdown - 1), 1000); return () => clearTimeout(timer); } }, [countdown]); return (

0}> {countdown > 0 ? ${countdown}秒后重试 : ‘发送验证码’}

); }; export default SmsVerification;


4 后端实现(Node.js + Express)

4.1 使用 Redis 限制请求频率

使用 Redis 记录每个手机号或 IP 的请求频率。 const express = require(’express’); const redis = require(‘redis’); const app = express(); const client = redis.createClient(); app.use(express.json()); // 限制每分钟最多发送 1 次验证码 app.post(’/api/send-sms’, async (req, res) => { const { phone, captcha } = req.body; // 验证图形验证码 if (!validateCaptcha(captcha)) { return res.status(400).json({ message: ‘图形验证码错误’ }); } const key = sms:${phone}; const count = await client.getAsync(key); if (count && parseInt(count) >= 1) { return res.status(429).json({ message: ‘请求过于频繁,请稍后再试’ }); } // 发送短信验证码 const code = generateRandomCode(); await sendSms(phone, code); // 记录请求次数 await client.setAsync(key, 1, ‘EX’, 60); // 60 秒内只能发送 1 次 res.json({ message: ‘验证码已发送’ }); }); // 启动服务器 app.listen(3000, () => { console.log(‘Server is running on port 3000’); });


4.2 验证码有效期和使用次数限制

在 Redis 中存储验证码,并设置有效期和使用次数。 app.post(’/api/verify-code’, async (req, res) => { const { phone, code } = req.body; const key = code:${phone}; const storedCode = await client.getAsync(key); if (!storedCode || storedCode !== code) { return res.status(400).json({ message: ‘验证码错误或已过期’ }); } // 验证成功后删除验证码 await client.delAsync(key); res.json({ message: ‘验证成功’ }); });


4.3 黑名单机制

将频繁请求验证码的 IP 或手机号加入黑名单。 app.post(’/api/send-sms’, async (req, res) => { const { phone, captcha } = req.body; const ip = req.ip; // 检查黑名单 const isBlacklisted = await client.getAsync(blacklist:${ip}); if (isBlacklisted) { return res.status(403).json({ message: ‘您的 IP 已被限制’ }); } // 其他逻辑… });


5 总结

5.1 核心防御措施

  • 图形验证码 :防止自动化脚本。
  • 请求频率限制 :限制单位时间内的请求次数。
  • 验证码有效期 :设置较短的验证码有效期。
  • 黑名单机制 :限制恶意 IP 或手机号。

5.2 注意事项

  • 用户体验 :在保证安全的同时,尽量减少对正常用户的干扰。
  • 日志监控 :记录验证码请求日志,及时发现异常行为。
  • 多维度限制 :结合 IP、设备指纹、用户行为等多维度进行限制。 通过以上措施,可以有效防止手机验证码被刷,保障系统的安全性和稳定性。