mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-13 05:59:01 +08:00
feat(upms): 增强短信验证码注册功能和安全机制
- 在RegisterUserDTO中新增短信验证码字段 - 用户注册时增加短信验证码校验逻辑 - 合并短信验证码发送接口为单一API - 增加IP频率限制防止短信轰炸攻击 - 优化验证码校验失败的错误返回类型
This commit is contained in:
1 parent
e959811fa2
commit
13d17923e4
4 files changed
+46
-24
No files matched your search
+5
@@ -36,4 +36,9 @@ public class RegisterUserDTO {
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 短信验证码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
}
|
||||
+12
-22
@@ -182,26 +182,16 @@ public class SysMessageController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信(验证码)
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param mobile 手机号 (需要注册,对外提供,安全性第一)
|
||||
* @return {@link R }
|
||||
* @param mobile 手机号
|
||||
* @param registered 是否已注册,默认true
|
||||
* @return 发送结果
|
||||
*/
|
||||
@Inner(value = false)
|
||||
@GetMapping("/send/smsCode")
|
||||
public R sendSmsCode(@RequestParam String mobile) {
|
||||
return sysMessageService.sendSmsCode(mobile, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送内部短信验证码
|
||||
*
|
||||
* @param mobile 手机号码 (系统内不一定存在)
|
||||
* @return 发送结果
|
||||
*/
|
||||
@GetMapping("/send/smsInnerCode")
|
||||
public R sendSmsInnerCode(@RequestParam String mobile) {
|
||||
return sysMessageService.sendSmsCode(mobile, false);
|
||||
public R sendSmsCode(@RequestParam String mobile, @RequestParam(required = false, defaultValue = "true") boolean registered) {
|
||||
return sysMessageService.sendSmsCode(mobile, registered);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,12 +224,12 @@ public class SysMessageController {
|
||||
*/
|
||||
@PostMapping("/send/hook")
|
||||
public R sendWebhook(@Valid @RequestBody MessageHookDTO messageHookDTO) {
|
||||
return sysMessageService.sendHook(messageHookDTO);
|
||||
}
|
||||
return sysMessageService.sendHook(messageHookDTO);
|
||||
}
|
||||
|
||||
@GetMapping("/list/hook")
|
||||
public R listHookBizCode(MessageHookDTO messageHookDTO) {
|
||||
return sysMessageService.listHookBizCode(messageHookDTO);
|
||||
}
|
||||
@GetMapping("/list/hook")
|
||||
public R listHookBizCode(MessageHookDTO messageHookDTO) {
|
||||
return sysMessageService.listHookBizCode(messageHookDTO);
|
||||
}
|
||||
|
||||
}
|
||||
+19
-2
@@ -42,7 +42,9 @@ import com.pig4cloud.pigx.common.core.constant.enums.YesNoEnum;
|
||||
import com.pig4cloud.pigx.common.core.exception.CheckedException;
|
||||
import com.pig4cloud.pigx.common.core.util.MsgUtils;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.core.util.WebUtils;
|
||||
import com.pig4cloud.pigx.common.data.cache.RedisUtils;
|
||||
import com.pig4cloud.pigx.common.data.resolver.ParamResolver;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.common.file.core.FileTemplate;
|
||||
@@ -279,12 +281,27 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
*/
|
||||
@Override
|
||||
public R<Boolean> sendSmsCode(String mobile, boolean registered) {
|
||||
// IP 限制校验,单位时间内同一IP发送次数限制
|
||||
String clientIp = WebUtils.getIP();
|
||||
String ipLimitKey = CacheConstants.DEFAULT_CODE_KEY + "IP_LIMIT:" + clientIp;
|
||||
if (StrUtil.isNotBlank(clientIp)) {
|
||||
Long maxTimes = ParamResolver.getLong("SMS_IP_LIMIT_TIMES", 5L);
|
||||
Long ipSendTimes = RedisUtils.increment(ipLimitKey, 1L);
|
||||
// 设置过期时间
|
||||
RedisUtils.expire(ipLimitKey, SecurityConstants.CODE_TIME);
|
||||
|
||||
if (ipSendTimes > maxTimes) {
|
||||
log.info("IP发送验证码过于频繁:{}, 已发送{}次", clientIp, ipSendTimes);
|
||||
return R.failed(Boolean.FALSE, MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_SMS_OFTEN));
|
||||
}
|
||||
}
|
||||
|
||||
List<SysUser> userList = TenantBroker
|
||||
.noneAs(() -> userMapper.selectList(Wrappers.<SysUser>query().lambda().eq(SysUser::getPhone, mobile)));
|
||||
|
||||
if (registered && CollUtil.isEmpty(userList)) {
|
||||
log.info("手机号未注册:{}", mobile);
|
||||
return R.ok(Boolean.FALSE, MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_PHONE_UNREGISTERED, mobile));
|
||||
return R.failed(Boolean.FALSE, MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_PHONE_UNREGISTERED, mobile));
|
||||
}
|
||||
|
||||
String codeObj = RedisUtils
|
||||
@@ -292,7 +309,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
|
||||
if (StrUtil.isNotBlank(codeObj)) {
|
||||
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
|
||||
return R.ok(Boolean.FALSE, MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_SMS_OFTEN));
|
||||
return R.failed(Boolean.FALSE, MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_SMS_OFTEN));
|
||||
}
|
||||
|
||||
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
|
||||
|
||||
+10
@@ -533,6 +533,16 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<Boolean> registerUser(RegisterUserDTO userDto) {
|
||||
// 校验短信验证码
|
||||
if (StrUtil.isBlank(userDto.getCode())) {
|
||||
return R.failed(MsgUtils.getMessage(UpmsErrorCodes.SYS_PARAM_ILLEGAL));
|
||||
}
|
||||
String codeObj = RedisUtils
|
||||
.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + userDto.getPhone());
|
||||
if (!StrUtil.equals(codeObj, userDto.getCode())) {
|
||||
return R.failed(MsgUtils.getMessage(UpmsErrorCodes.SYS_APP_SMS_ERROR));
|
||||
}
|
||||
|
||||
// 判断用户名是否存在
|
||||
boolean usernameExists = TenantBroker
|
||||
.noneAs(() -> this.exists(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, userDto.getUsername())));
|
||||
|
||||
Reference in new issue
Block a user