feat(auth): 密码重置邮件队列化与限流优化

- 邮件发送改为异步队列处理,避免并发导致发送失败
- 新增 Email 维度限流(30秒冷却期),防止邮件轰炸
- Token 验证使用常量时间比较,防止时序攻击
- 重构代码消除冗余,提取公共验证逻辑
This commit is contained in:
shaw
2026-01-24 22:33:45 +08:00
parent 43a1031e38
commit 9cc8352593
25 changed files with 1497 additions and 114 deletions

View File

@@ -271,7 +271,36 @@ export default {
code: 'Code',
state: 'State',
fullUrl: 'Full URL'
}
},
// Forgot password
forgotPassword: 'Forgot password?',
forgotPasswordTitle: 'Reset Your Password',
forgotPasswordHint: 'Enter your email address and we will send you a link to reset your password.',
sendResetLink: 'Send Reset Link',
sendingResetLink: 'Sending...',
sendResetLinkFailed: 'Failed to send reset link. Please try again.',
resetEmailSent: 'Reset Link Sent',
resetEmailSentHint: 'If an account exists with this email, you will receive a password reset link shortly. Please check your inbox and spam folder.',
backToLogin: 'Back to Login',
rememberedPassword: 'Remembered your password?',
// Reset password
resetPasswordTitle: 'Set New Password',
resetPasswordHint: 'Enter your new password below.',
newPassword: 'New Password',
newPasswordPlaceholder: 'Enter your new password',
confirmPassword: 'Confirm Password',
confirmPasswordPlaceholder: 'Confirm your new password',
confirmPasswordRequired: 'Please confirm your password',
passwordsDoNotMatch: 'Passwords do not match',
resetPassword: 'Reset Password',
resettingPassword: 'Resetting...',
resetPasswordFailed: 'Failed to reset password. Please try again.',
passwordResetSuccess: 'Password Reset Successful',
passwordResetSuccessHint: 'Your password has been reset. You can now sign in with your new password.',
invalidResetLink: 'Invalid Reset Link',
invalidResetLinkHint: 'This password reset link is invalid or has expired. Please request a new one.',
requestNewResetLink: 'Request New Reset Link',
invalidOrExpiredToken: 'The password reset link is invalid or has expired. Please request a new one.'
},
// Dashboard
@@ -2743,7 +2772,9 @@ export default {
emailVerification: 'Email Verification',
emailVerificationHint: 'Require email verification for new registrations',
promoCode: 'Promo Code',
promoCodeHint: 'Allow users to use promo codes during registration'
promoCodeHint: 'Allow users to use promo codes during registration',
passwordReset: 'Password Reset',
passwordResetHint: 'Allow users to reset their password via email'
},
turnstile: {
title: 'Cloudflare Turnstile',

View File

@@ -268,7 +268,36 @@ export default {
code: '授权码',
state: '状态',
fullUrl: '完整URL'
}
},
// 忘记密码
forgotPassword: '忘记密码?',
forgotPasswordTitle: '重置密码',
forgotPasswordHint: '输入您的邮箱地址,我们将向您发送密码重置链接。',
sendResetLink: '发送重置链接',
sendingResetLink: '发送中...',
sendResetLinkFailed: '发送重置链接失败,请重试。',
resetEmailSent: '重置链接已发送',
resetEmailSentHint: '如果该邮箱已注册,您将很快收到密码重置链接。请检查您的收件箱和垃圾邮件文件夹。',
backToLogin: '返回登录',
rememberedPassword: '想起密码了?',
// 重置密码
resetPasswordTitle: '设置新密码',
resetPasswordHint: '请在下方输入您的新密码。',
newPassword: '新密码',
newPasswordPlaceholder: '输入新密码',
confirmPassword: '确认密码',
confirmPasswordPlaceholder: '再次输入新密码',
confirmPasswordRequired: '请确认您的密码',
passwordsDoNotMatch: '两次输入的密码不一致',
resetPassword: '重置密码',
resettingPassword: '重置中...',
resetPasswordFailed: '重置密码失败,请重试。',
passwordResetSuccess: '密码重置成功',
passwordResetSuccessHint: '您的密码已重置。现在可以使用新密码登录。',
invalidResetLink: '无效的重置链接',
invalidResetLinkHint: '此密码重置链接无效或已过期。请重新请求一个新链接。',
requestNewResetLink: '请求新的重置链接',
invalidOrExpiredToken: '密码重置链接无效或已过期。请重新请求一个新链接。'
},
// Dashboard
@@ -2896,7 +2925,9 @@ export default {
emailVerification: '邮箱验证',
emailVerificationHint: '新用户注册时需要验证邮箱',
promoCode: '优惠码',
promoCodeHint: '允许用户在注册时使用优惠码'
promoCodeHint: '允许用户在注册时使用优惠码',
passwordReset: '忘记密码',
passwordResetHint: '允许用户通过邮箱重置密码'
},
turnstile: {
title: 'Cloudflare Turnstile',