From 71589ab13a92e3abb1bf53680f3ebf9325f124a1 Mon Sep 17 00:00:00 2001 From: MichaelWin Date: Mon, 9 Feb 2026 12:24:31 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=94=B9=E8=BF=9B=E3=80=91=E7=9F=AD?= =?UTF-8?q?=E4=BF=A1=E5=8F=91=E9=80=81=E5=A2=9E=E5=8A=A0=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/service/impl/UserServiceImpl.java | 28 ++++++++++---- .../service/impl/VerifyCodeServiceImpl.java | 24 +++++++++--- .../java/com/corewing/app/util/RedisUtil.java | 37 +++++++++++++++++++ .../resources/i18n/messages_en_US.properties | 1 + .../resources/i18n/messages_zh_CN.properties | 1 + 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/corewing/app/service/impl/UserServiceImpl.java b/src/main/java/com/corewing/app/service/impl/UserServiceImpl.java index 408fb4e..b5d246a 100755 --- a/src/main/java/com/corewing/app/service/impl/UserServiceImpl.java +++ b/src/main/java/com/corewing/app/service/impl/UserServiceImpl.java @@ -25,6 +25,7 @@ import javax.annotation.Resource; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * 应用用户 Service 实现类 @@ -315,14 +316,27 @@ public class UserServiceImpl extends ServiceImpl implements Us // 发送验证码 if (StringUtils.hasText(user.getTelephone())) { - // 发送短信验证码 - boolean success = smsBaoUtil.sendVerifyCode(user.getTelephone(), code); - if (!success) { - throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed")); + + // 获取当前ip + String clientIp = IpUtil.getClientIp(CommonServletUtil.getRequest()); + clientIp = clientIp.replaceAll(":", ""); + // 使用 setIfAbsent 初始化计数器(只在键不存在时创建,并设置过期时间为1天) + boolean isNew = redisUtil.setIfAbsent("exceed_" + clientIp, 1, 1, TimeUnit.DAYS); + // 如果键已存在,递增计数器 + long sendCount = isNew ? 1 : redisUtil.incr("exceed_" + clientIp, 1); + + if (sendCount <= 4) { + + // 发送短信验证码 + boolean success = smsBaoUtil.sendVerifyCode(user.getTelephone(), code); + if (!success) { + throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed")); + } + Map map = new HashMap<>(); + map.put("account", user.getTelephone()); + return Result.success(map); } - Map map = new HashMap<>(); - map.put("account", user.getTelephone()); - return Result.success(map); + throw new RuntimeException(I18nUtil.getMessage("error.sms.send.exceed")); } else { // 发送邮件验证码 boolean success = emailUtil.sendVerifyCode(user.getEmail(), code); diff --git a/src/main/java/com/corewing/app/service/impl/VerifyCodeServiceImpl.java b/src/main/java/com/corewing/app/service/impl/VerifyCodeServiceImpl.java index 34909b7..02c3f99 100755 --- a/src/main/java/com/corewing/app/service/impl/VerifyCodeServiceImpl.java +++ b/src/main/java/com/corewing/app/service/impl/VerifyCodeServiceImpl.java @@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import java.util.Random; +import java.util.concurrent.TimeUnit; /** * 验证码服务实现类 @@ -30,6 +30,7 @@ public class VerifyCodeServiceImpl implements VerifyCodeService { @Override public boolean sendCode(String account, String type) { + if (!StringUtils.hasText(account)) { throw new RuntimeException(I18nUtil.getMessage("error.account.empty")); } @@ -53,10 +54,23 @@ public class VerifyCodeServiceImpl implements VerifyCodeService { // 发送验证码 if (AccountUtil.isPhone(account)) { - // 发送短信验证码 - boolean success = smsBaoUtil.sendVerifyCode(account, code); - if (!success) { - throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed")); + // 获取当前ip + String clientIp = IpUtil.getClientIp(CommonServletUtil.getRequest()); + clientIp = clientIp.replaceAll(":", ""); + // 校验IP发短信次数 + // 使用 setIfAbsent 初始化计数器(只在键不存在时创建,并设置过期时间为1天) + boolean isNew = redisUtil.setIfAbsent("exceed_" + clientIp, 1, 1, TimeUnit.DAYS); + // 如果键已存在,递增计数器 + long sendCount = isNew ? 1 : redisUtil.incr("exceed_" + clientIp, 1); + + if (sendCount <= 4) { + // 发送短信验证码 + boolean success = smsBaoUtil.sendVerifyCode(account, code); + if (!success) { + throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed")); + } + } else { + throw new RuntimeException(I18nUtil.getMessage("error.sms.send.exceed")); } } else { // 发送邮件验证码 diff --git a/src/main/java/com/corewing/app/util/RedisUtil.java b/src/main/java/com/corewing/app/util/RedisUtil.java index 2ba1cc8..85e9154 100644 --- a/src/main/java/com/corewing/app/util/RedisUtil.java +++ b/src/main/java/com/corewing/app/util/RedisUtil.java @@ -133,6 +133,43 @@ public class RedisUtil { } } + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(天) + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, Integer time, TimeUnit timeUnit) { + try { + redisTemplate.opsForValue().set(key, value, time, timeUnit); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间(仅在键不存在时设置) + * + * @param key 键 + * @param value 值 + * @param time 时间 + * @param timeUnit 时间单位 + * @return true成功 false失败(键已存在或设置失败) + */ + public boolean setIfAbsent(String key, Object value, long time, TimeUnit timeUnit) { + try { + Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit); + return result != null && result; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** * 递增 * diff --git a/src/main/resources/i18n/messages_en_US.properties b/src/main/resources/i18n/messages_en_US.properties index 875d4ae..68a0814 100644 --- a/src/main/resources/i18n/messages_en_US.properties +++ b/src/main/resources/i18n/messages_en_US.properties @@ -35,6 +35,7 @@ error.verify.type.empty=Verification type cannot be empty error.account.format.invalid=Please enter a valid phone number or email error.sms.send.failed=SMS sending failed, please try again later error.email.send.failed=Email sending failed, please try again later +error.sms.send.exceed=SMS sending failed, the number of available times on that day exceeded # ==================== Feedback Module ==================== # Feedback Controller diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index e8c41f8..f1ce2f3 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -35,6 +35,7 @@ error.verify.type.empty=验证码类型不能为空 error.account.format.invalid=请输入正确的手机号或邮箱 error.sms.send.failed=短信发送失败,请稍后重试 error.email.send.failed=邮件发送失败,请稍后重试 +error.sms.send.exceed=短信发送失败,当天可用次数超出 # ==================== 反馈模块 ==================== # 反馈Controller