From 513954ccf1cd006a6cb2cf4dd63897e4351745b3 Mon Sep 17 00:00:00 2001 From: 777 <123@qwe.com> Date: Fri, 5 Dec 2025 18:27:51 +0800 Subject: [PATCH] nnnn --- doc/20251205.sql | 1 + .../controller/cai/app/AuthAppController.java | 17 ++- .../com/ruoyi/cai/auth/CaiLoginManager.java | 13 +- .../cai/controller/IpBlackController.java | 4 +- .../cai/controller/IpRecordController.java | 6 +- .../java/com/ruoyi/cai/domain/IpBlack.java | 2 +- .../java/com/ruoyi/cai/domain/IpRecord.java | 2 + .../cai/dto/admin/vo/IpRecordAdminVO.java | 10 ++ .../ruoyi/cai/dto/commom/user/MinUser.java | 1 + .../com/ruoyi/cai/mapper/IpRecordMapper.java | 5 + .../com/ruoyi/cai/service/IpBlackService.java | 3 + .../ruoyi/cai/service/IpRecordService.java | 6 + .../cai/service/impl/IpBlackServiceImpl.java | 18 +++ .../cai/service/impl/IpRecordServiceImpl.java | 118 ++++++++++++++++++ .../service/impl/SmsVerifyServiceImpl.java | 15 +++ .../resources/mapper/cai/IpRecordMapper.xml | 14 ++- .../main/resources/mapper/cai/UserMapper.xml | 2 +- 17 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 ruoyi-cai/src/main/java/com/ruoyi/cai/dto/admin/vo/IpRecordAdminVO.java diff --git a/doc/20251205.sql b/doc/20251205.sql index a0ad48ef..1482890a 100644 --- a/doc/20251205.sql +++ b/doc/20251205.sql @@ -1,6 +1,7 @@ CREATE TABLE `cai_ip_record` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '子账户ID', + `count_date` date NOT NULL COMMENT '统计日期', `ip_addr` varchar(100) NOT NULL COMMENT 'IP地址', `path_addr` varchar(255) NULL COMMENT '请求地址', `business_id` varchar(255) NULL, diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/cai/app/AuthAppController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/cai/app/AuthAppController.java index c245cbbd..673dae51 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/cai/app/AuthAppController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/cai/app/AuthAppController.java @@ -10,6 +10,8 @@ import com.ruoyi.cai.kit.VerificationCodeCheck; import com.ruoyi.cai.manager.CurrentUserManager; import com.ruoyi.cai.manager.LoginAfterManager; import com.ruoyi.cai.manager.SystemConfigManager; +import com.ruoyi.cai.service.IpBlackService; +import com.ruoyi.cai.service.IpRecordService; import com.ruoyi.cai.service.SmsVerifyService; import com.ruoyi.cai.service.UserService; import com.ruoyi.common.annotation.Log; @@ -142,15 +144,24 @@ public class AuthAppController { @Autowired private LoginAfterManager loginAfterManager; + @Autowired + private IpRecordService ipRecordService; + @Autowired + private IpBlackService ipBlackService; @PostMapping("/login") @Operation(summary = "登陆") @Log(title = "登陆", businessType = BusinessType.OTHER, isSaveDb = false) public R login(@Validated @RequestBody LoginCaiUser loginBody){ LoginVo vo = new LoginVo(); - String token = caiLoginManager.login(loginBody.getUsername(), loginBody.getPassword()); - vo.setToken(token); - vo.setUserInfo(currentUserManager.currentInfo()); + try { + String token = caiLoginManager.login(loginBody.getUsername(), loginBody.getPassword()); + vo.setToken(token); + vo.setUserInfo(currentUserManager.currentInfo()); + }catch (Exception e){ + ipRecordService.saveLoginIp(ServletUtils.getClientIP()); + throw e; + } // 异步调用通知 // loginAfterManager.loginAfter(LoginHelper.getUserId()); return R.ok(vo); diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/auth/CaiLoginManager.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/auth/CaiLoginManager.java index 7c5b8818..edd15162 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/auth/CaiLoginManager.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/auth/CaiLoginManager.java @@ -93,15 +93,24 @@ public class CaiLoginManager { private IgnoreDataService ignoreDataService; @Autowired private AmqpHttpProducer amqpHttpProducer; + @Autowired + private IpRecordService ipRecordService; + @Autowired + private IpBlackService ipBlackService; public String login(String username,String password){ + String clientIP = ServletUtils.getClientIP(); + Boolean b = ipBlackService.checkIp(clientIP); + if(b){ + log.error("登录拦截了异常IP={}", clientIP); + throw new ServiceException("40305"); + } User user = userService.getByUsername(username); if(user == null){ - throw new ServiceException("用户不存在或密码错误"); } String imei = ServletUtils.getImei(); - UserForbidManager.CheckForbid forbid = userForbidManager.checkForbid(user.getId(), user.getUsercode(), imei, ServletUtils.getClientIP()); + UserForbidManager.CheckForbid forbid = userForbidManager.checkForbid(user.getId(), user.getUsercode(), imei, clientIP); if(forbid != null && forbid.isForbid()){ throw new ServiceException(forbid.getMessage()); } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpBlackController.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpBlackController.java index 156e3e48..e743f957 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpBlackController.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpBlackController.java @@ -64,7 +64,9 @@ public class IpBlackController extends BaseController { @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody IpBlack bo) { - return toAjax(ipBlackService.save(bo)); + bo.setEnableStatus(1); + ipBlackService.saveIp(bo); + return R.ok(); } /** diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpRecordController.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpRecordController.java index 122cd7bf..678c6f44 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpRecordController.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/controller/IpRecordController.java @@ -1,9 +1,11 @@ package com.ruoyi.cai.controller; import cn.dev33.satoken.annotation.SaCheckPermission; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.cai.domain.IpRecord; +import com.ruoyi.cai.dto.admin.vo.IpRecordAdminVO; import com.ruoyi.cai.service.IpRecordService; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; @@ -41,8 +43,8 @@ public class IpRecordController extends BaseController { */ @SaCheckPermission("cai:ipRecord:list") @GetMapping("/list") - public TableDataInfo list(IpRecord bo, PageQuery pageQuery) { - Page page = ipRecordService.page(pageQuery.build(), Wrappers.lambdaQuery(bo)); + public TableDataInfo list(IpRecordAdminVO bo, PageQuery pageQuery) { + IPage page = ipRecordService.pageAdmin(bo,pageQuery); return TableDataInfo.build(page); } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpBlack.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpBlack.java index ef31fa4f..9a4d3c19 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpBlack.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpBlack.java @@ -32,7 +32,7 @@ public class IpBlack implements Serializable { /** * 是否开启 */ - private Long enableStatus; + private Integer enableStatus; private LocalDateTime createTime; diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpRecord.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpRecord.java index d0603272..31677239 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpRecord.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/domain/IpRecord.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; +import java.time.LocalDate; import java.time.LocalDateTime; /** @@ -25,6 +26,7 @@ public class IpRecord implements Serializable{ */ @TableId(value = "id",type = IdType.AUTO) private String id; + private LocalDate countDate; /** * IP地址 */ diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/admin/vo/IpRecordAdminVO.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/admin/vo/IpRecordAdminVO.java new file mode 100644 index 00000000..8a81c7d4 --- /dev/null +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/admin/vo/IpRecordAdminVO.java @@ -0,0 +1,10 @@ +package com.ruoyi.cai.dto.admin.vo; + +import com.ruoyi.cai.domain.IpRecord; +import lombok.Data; + +@Data +public class IpRecordAdminVO extends IpRecord { + private boolean black; + private Integer minNumber; +} diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/commom/user/MinUser.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/commom/user/MinUser.java index 65968325..4026b87f 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/commom/user/MinUser.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/dto/commom/user/MinUser.java @@ -6,6 +6,7 @@ import lombok.Data; public class MinUser { private Long id; private Integer gender; + private String mobile; /** * 隐身模式 0-关闭 1-打开 */ diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/mapper/IpRecordMapper.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/mapper/IpRecordMapper.java index 6c62e0d0..12558ddb 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/mapper/IpRecordMapper.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/mapper/IpRecordMapper.java @@ -1,7 +1,11 @@ package com.ruoyi.cai.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.cai.domain.IpRecord; +import com.ruoyi.cai.dto.admin.vo.IpRecordAdminVO; +import org.apache.ibatis.annotations.Param; /** * ip访问记录Mapper接口 @@ -11,4 +15,5 @@ import com.ruoyi.cai.domain.IpRecord; */ public interface IpRecordMapper extends BaseMapper { + IPage pageAdmin(Page build, @Param("bo") IpRecordAdminVO bo); } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpBlackService.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpBlackService.java index 471bbdc8..8cbc4ae2 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpBlackService.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpBlackService.java @@ -11,4 +11,7 @@ import com.ruoyi.cai.domain.IpBlack; */ public interface IpBlackService extends IService { + Boolean checkIp(String clientIP); + + void saveIp(IpBlack ipBlack); } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpRecordService.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpRecordService.java index 90192cb9..14924c03 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpRecordService.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/IpRecordService.java @@ -1,7 +1,10 @@ package com.ruoyi.cai.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.cai.domain.IpRecord; +import com.ruoyi.cai.dto.admin.vo.IpRecordAdminVO; +import com.ruoyi.common.core.domain.PageQuery; /** * ip访问记录Service接口 @@ -10,4 +13,7 @@ import com.ruoyi.cai.domain.IpRecord; * @date 2025-12-05 */ public interface IpRecordService extends IService { + IPage pageAdmin(IpRecordAdminVO bo, PageQuery pageQuery); + + void saveLoginIp(String clientIP); } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpBlackServiceImpl.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpBlackServiceImpl.java index 2f94df8b..58bedcb6 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpBlackServiceImpl.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpBlackServiceImpl.java @@ -1,9 +1,11 @@ package com.ruoyi.cai.service.impl; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.cai.domain.IpBlack; import com.ruoyi.cai.mapper.IpBlackMapper; import com.ruoyi.cai.service.IpBlackService; +import com.ruoyi.common.exception.ServiceException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -17,4 +19,20 @@ import org.springframework.stereotype.Service; @Service public class IpBlackServiceImpl extends ServiceImpl implements IpBlackService { + @Override + public Boolean checkIp(String clientIP) { + boolean exists = this.exists(Wrappers.lambdaQuery(IpBlack.class).eq(IpBlack::getIpAddr, clientIP) + .eq(IpBlack::getEnableStatus, 1)); + return exists; + } + + @Override + public void saveIp(IpBlack ipBlack){ + boolean exists = this.exists(Wrappers.lambdaQuery(IpBlack.class).eq(IpBlack::getIpAddr, ipBlack.getIpAddr())); + if(exists){ + throw new ServiceException("IP已经存在"); + } + this.save(ipBlack); + } + } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpRecordServiceImpl.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpRecordServiceImpl.java index c9f2b580..67239ff1 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpRecordServiceImpl.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/IpRecordServiceImpl.java @@ -1,12 +1,25 @@ package com.ruoyi.cai.service.impl; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.cai.domain.IpRecord; +import com.ruoyi.cai.dto.admin.vo.IpRecordAdminVO; import com.ruoyi.cai.mapper.IpRecordMapper; import com.ruoyi.cai.service.IpRecordService; +import com.ruoyi.common.core.domain.PageQuery; import lombok.RequiredArgsConstructor; +import org.redisson.api.RAtomicLong; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.TimeUnit; + /** * ip访问记录Service业务层处理 * @@ -17,4 +30,109 @@ import org.springframework.stereotype.Service; @Service public class IpRecordServiceImpl extends ServiceImpl implements IpRecordService { + @Autowired + private RedissonClient redissonClient; + + + @Override + public IPage pageAdmin(IpRecordAdminVO bo, PageQuery pageQuery){ + IPage page = baseMapper.pageAdmin(pageQuery.build(), bo); + return page; + } + + @Override + public void saveLoginIp(String ip) { + long l = saveIp(ip); + if(l < 5){ + return; + } + if(l % 5 == 0){ + try { + this.saveIpDb(ip); + } catch (InterruptedException e) { + log.error("保存IP失败",e); + } + } + } + + + private void saveIpDb(String ip) throws InterruptedException { + IpRecord ipRecord = getByIpAndDate(ip, null); + if(ipRecord == null){ + String lockKey = getLockKey(ip); + RLock lock = redissonClient.getLock(lockKey); + try { + boolean b = lock.tryLock(5, TimeUnit.SECONDS); + if(b){ + ipRecord = getByIpAndDate(ip, null); + if(ipRecord == null){ + IpRecord record = new IpRecord(); + record.setIpAddr(ip); + long numb = getIp(ip); + record.setPathAddr("/api/auth/login"); + record.setCountDate(LocalDate.now()); + record.setNumber(numb); + record.setUpdateTime(LocalDateTime.now()); + this.save(record); + }else{ + long numb = getIp(ip); + IpRecord record = new IpRecord(); + record.setId(ipRecord.getId()); + record.setNumber(numb); + record.setUpdateTime(LocalDateTime.now()); + this.updateById(record); + } + } + } finally { + lock.unlock(); + } + }else{ + long numb = getIp(ip); + IpRecord record = new IpRecord(); + record.setId(ipRecord.getId()); + record.setNumber(numb); + record.setUpdateTime(LocalDateTime.now()); + this.updateById(record); + } + + } + + public static String KEY_LOCK = "cai:ipRecordLock:%s"; + + public static String getLockKey(String ip){ + return String.format(KEY_LOCK, ip); + } + + private IpRecord getByIpAndDate(String ip,LocalDate date){ + if(date == null){ + date = LocalDate.now(); + } + return this.getOne(Wrappers.lambdaQuery(IpRecord.class).eq(IpRecord::getIpAddr, ip).eq(IpRecord::getCountDate, date).last("limit 1")); + } + + public static String KEY = "cai:ipRecord:%s:%s"; + + private String getNow(){ + return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); + } + + private String getKey(String ip){ + return String.format(KEY, ip, getNow()); + } + + public long getIp(String ip){ + String key = getKey(ip); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + return atomicLong.get(); + } + + public long saveIp(String ip){ + String key = getKey(ip); + RAtomicLong atomicLong = redissonClient.getAtomicLong(key); + long l = atomicLong.incrementAndGet(); + return l; + } + + + } diff --git a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/SmsVerifyServiceImpl.java b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/SmsVerifyServiceImpl.java index bdee00f2..7328e48b 100644 --- a/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/SmsVerifyServiceImpl.java +++ b/ruoyi-cai/src/main/java/com/ruoyi/cai/service/impl/SmsVerifyServiceImpl.java @@ -3,9 +3,11 @@ package com.ruoyi.cai.service.impl; import cn.hutool.core.util.RandomUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.api.client.util.SecurityUtils; import com.ruoyi.cai.domain.SmsVerify; import com.ruoyi.cai.domain.User; import com.ruoyi.cai.domain.UserInfo; +import com.ruoyi.cai.dto.commom.user.MinUser; import com.ruoyi.cai.enums.CodeEnum; import com.ruoyi.cai.enums.SystemConfigEnum; import com.ruoyi.cai.kit.AliSmsKit; @@ -17,6 +19,7 @@ import com.ruoyi.cai.service.SmsVerifyService; import com.ruoyi.cai.service.UserInfoService; import com.ruoyi.cai.service.UserService; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.ServletUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -81,12 +84,24 @@ public class SmsVerifyServiceImpl extends ServiceImpl throw new ServiceException("手机号已经被注册使用!"); } }else if(codeEnum == CodeEnum.RESET_PASSWORD){ + Long userId = LoginHelper.getUserId(); + MinUser miniUser = userService.getMinUserById(userId); + if(miniUser == null || !mobile.equalsIgnoreCase(miniUser.getMobile())){ + log.error("手机号与登录手机号不一致"); + throw new ServiceException("手机号未注册!"); + } long count = userService.count(Wrappers.lambdaQuery(User.class) .eq(User::getMobile, mobile)); if(count == 0){ throw new ServiceException("手机号未注册!"); } }else if(codeEnum == CodeEnum.RESET_ADOLESCENT){ + Long userId = LoginHelper.getUserId(); + MinUser miniUser = userService.getMinUserById(userId); + if(miniUser == null || !mobile.equalsIgnoreCase(miniUser.getMobile())){ + log.error("手机号与登录手机号不一致"); + throw new ServiceException("手机号未注册!"); + } long count = userService.count(Wrappers.lambdaQuery(User.class) .eq(User::getMobile, mobile)); if(count == 0){ diff --git a/ruoyi-cai/src/main/resources/mapper/cai/IpRecordMapper.xml b/ruoyi-cai/src/main/resources/mapper/cai/IpRecordMapper.xml index 71e40d6d..3c760eb7 100644 --- a/ruoyi-cai/src/main/resources/mapper/cai/IpRecordMapper.xml +++ b/ruoyi-cai/src/main/resources/mapper/cai/IpRecordMapper.xml @@ -15,5 +15,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + diff --git a/ruoyi-cai/src/main/resources/mapper/cai/UserMapper.xml b/ruoyi-cai/src/main/resources/mapper/cai/UserMapper.xml index 9eea8635..6775dfe3 100644 --- a/ruoyi-cai/src/main/resources/mapper/cai/UserMapper.xml +++ b/ruoyi-cai/src/main/resources/mapper/cai/UserMapper.xml @@ -100,7 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" limit 20