This commit is contained in:
777
2025-12-05 18:27:51 +08:00
parent 84d42a3af2
commit 513954ccf1
17 changed files with 226 additions and 11 deletions

View File

@@ -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());
}

View File

@@ -64,7 +64,9 @@ public class IpBlackController extends BaseController {
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody IpBlack bo) {
return toAjax(ipBlackService.save(bo));
bo.setEnableStatus(1);
ipBlackService.saveIp(bo);
return R.ok();
}
/**

View File

@@ -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<IpRecord> list(IpRecord bo, PageQuery pageQuery) {
Page<IpRecord> page = ipRecordService.page(pageQuery.build(), Wrappers.lambdaQuery(bo));
public TableDataInfo<IpRecordAdminVO> list(IpRecordAdminVO bo, PageQuery pageQuery) {
IPage<IpRecordAdminVO> page = ipRecordService.pageAdmin(bo,pageQuery);
return TableDataInfo.build(page);
}

View File

@@ -32,7 +32,7 @@ public class IpBlack implements Serializable {
/**
* 是否开启
*/
private Long enableStatus;
private Integer enableStatus;
private LocalDateTime createTime;

View File

@@ -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地址
*/

View File

@@ -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;
}

View File

@@ -6,6 +6,7 @@ import lombok.Data;
public class MinUser {
private Long id;
private Integer gender;
private String mobile;
/**
* 隐身模式 0-关闭 1-打开
*/

View File

@@ -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<IpRecord> {
IPage<IpRecordAdminVO> pageAdmin(Page<Object> build, @Param("bo") IpRecordAdminVO bo);
}

View File

@@ -11,4 +11,7 @@ import com.ruoyi.cai.domain.IpBlack;
*/
public interface IpBlackService extends IService<IpBlack> {
Boolean checkIp(String clientIP);
void saveIp(IpBlack ipBlack);
}

View File

@@ -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<IpRecord> {
IPage<IpRecordAdminVO> pageAdmin(IpRecordAdminVO bo, PageQuery pageQuery);
void saveLoginIp(String clientIP);
}

View File

@@ -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<IpBlackMapper,IpBlack> 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);
}
}

View File

@@ -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<IpRecordMapper,IpRecord> implements IpRecordService {
@Autowired
private RedissonClient redissonClient;
@Override
public IPage<IpRecordAdminVO> pageAdmin(IpRecordAdminVO bo, PageQuery pageQuery){
IPage<IpRecordAdminVO> 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;
}
}

View File

@@ -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<SmsVerifyMapper,SmsVerify>
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){