fix: 修复验证码请求429错误
问题: - 短时间内多次请求验证码触发限流(429 Too Many Requests) 修复: - 后端:验证码最小请求间隔从3秒改为1秒 - 前端:添加2秒防抖,避免重复请求 - 前端:429错误时保留已有验证码图片 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -755,7 +755,7 @@ const fileListLimiter = new RateLimiter({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 验证码最小请求间隔控制
|
// 验证码最小请求间隔控制
|
||||||
const CAPTCHA_MIN_INTERVAL = 3000; // 3秒
|
const CAPTCHA_MIN_INTERVAL = 1000; // 1秒
|
||||||
const captchaLastRequest = new TTLCache(15 * 60 * 1000); // 15分钟自动清理
|
const captchaLastRequest = new TTLCache(15 * 60 * 1000); // 15分钟自动清理
|
||||||
|
|
||||||
// 验证码防刷中间件
|
// 验证码防刷中间件
|
||||||
|
|||||||
@@ -622,52 +622,48 @@ handleDragLeave(e) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 刷新验证码(登录)
|
// 通用验证码加载函数(带防抖)
|
||||||
async refreshCaptcha() {
|
async loadCaptcha(targetField) {
|
||||||
|
// 防抖:2秒内不重复请求
|
||||||
|
const now = Date.now();
|
||||||
|
if (this._lastCaptchaTime && (now - this._lastCaptchaTime) < 2000) {
|
||||||
|
console.log('[验证码] 请求过于频繁,跳过');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._lastCaptchaTime = now;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${this.apiBase}/api/captcha?t=${Date.now()}`, {
|
const response = await axios.get(`${this.apiBase}/api/captcha?t=${now}`, {
|
||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
});
|
});
|
||||||
this.captchaUrl = URL.createObjectURL(response.data);
|
this[targetField] = URL.createObjectURL(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取验证码失败:', error);
|
console.error('获取验证码失败:', error);
|
||||||
|
// 如果是429错误,不清除已有验证码
|
||||||
|
if (error.response?.status !== 429) {
|
||||||
|
this[targetField] = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 刷新验证码(登录)
|
||||||
|
refreshCaptcha() {
|
||||||
|
this.loadCaptcha('captchaUrl');
|
||||||
|
},
|
||||||
|
|
||||||
// 刷新注册验证码
|
// 刷新注册验证码
|
||||||
async refreshRegisterCaptcha() {
|
refreshRegisterCaptcha() {
|
||||||
try {
|
this.loadCaptcha('registerCaptchaUrl');
|
||||||
const response = await axios.get(`${this.apiBase}/api/captcha?t=${Date.now()}`, {
|
|
||||||
responseType: 'blob'
|
|
||||||
});
|
|
||||||
this.registerCaptchaUrl = URL.createObjectURL(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取验证码失败:', error);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 刷新忘记密码验证码
|
// 刷新忘记密码验证码
|
||||||
async refreshForgotPasswordCaptcha() {
|
refreshForgotPasswordCaptcha() {
|
||||||
try {
|
this.loadCaptcha('forgotPasswordCaptchaUrl');
|
||||||
const response = await axios.get(`${this.apiBase}/api/captcha?t=${Date.now()}`, {
|
|
||||||
responseType: 'blob'
|
|
||||||
});
|
|
||||||
this.forgotPasswordCaptchaUrl = URL.createObjectURL(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取验证码失败:', error);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 刷新重发验证邮件验证码
|
// 刷新重发验证邮件验证码
|
||||||
async refreshResendVerifyCaptcha() {
|
refreshResendVerifyCaptcha() {
|
||||||
try {
|
this.loadCaptcha('resendVerifyCaptchaUrl');
|
||||||
const response = await axios.get(`${this.apiBase}/api/captcha?t=${Date.now()}`, {
|
|
||||||
responseType: 'blob'
|
|
||||||
});
|
|
||||||
this.resendVerifyCaptchaUrl = URL.createObjectURL(response.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取验证码失败:', error);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async resendVerification() {
|
async resendVerification() {
|
||||||
|
|||||||
Reference in New Issue
Block a user