| @ -0,0 +1,178 @@ | |||
| package org.jeecg.modules.system.controller; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import io.swagger.annotations.ApiParam; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.jeecg.common.api.vo.Result; | |||
| import org.jeecg.common.aspect.annotation.AutoLog; | |||
| import org.jeecg.modules.system.security.IpSecurityService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import java.util.List; | |||
| /** | |||
| * IP安全管理控制器 | |||
| * 提供IP黑白名单管理功能 | |||
| * | |||
| * @author system | |||
| * @date 2024 | |||
| */ | |||
| @Api(tags = "IP安全管理") | |||
| @RestController | |||
| @RequestMapping("/sys/ip/manage") | |||
| @Slf4j | |||
| public class IpSecurityController { | |||
| @Autowired | |||
| private IpSecurityService ipSecurityService; | |||
| @AutoLog(value = "获取黑名单IP列表") | |||
| @ApiOperation(value = "获取黑名单IP列表", notes = "获取所有被禁止的IP地址") | |||
| @GetMapping("/blacklist") | |||
| public Result<List<IpSecurityService.IpInfo>> getBlacklistIps() { | |||
| try { | |||
| List<IpSecurityService.IpInfo> blacklistIps = ipSecurityService.getBlacklistIps(); | |||
| return Result.ok(blacklistIps); | |||
| } catch (Exception e) { | |||
| log.error("获取黑名单IP列表失败", e); | |||
| return Result.error("获取黑名单IP列表失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "获取白名单IP列表") | |||
| @ApiOperation(value = "获取白名单IP列表", notes = "获取所有白名单IP地址") | |||
| @GetMapping("/whitelist") | |||
| public Result<List<IpSecurityService.IpInfo>> getWhitelistIps() { | |||
| try { | |||
| List<IpSecurityService.IpInfo> whitelistIps = ipSecurityService.getWhitelistIps(); | |||
| return Result.ok(whitelistIps); | |||
| } catch (Exception e) { | |||
| log.error("获取白名单IP列表失败", e); | |||
| return Result.error("获取白名单IP列表失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "添加IP到黑名单") | |||
| @ApiOperation(value = "添加IP到黑名单", notes = "手动将IP地址加入黑名单") | |||
| @PostMapping("/blacklist/add") | |||
| public Result<String> addToBlacklist( | |||
| @ApiParam(value = "IP地址", required = true) @RequestParam String ip, | |||
| @ApiParam(value = "禁止时长(分钟)", required = false) @RequestParam(defaultValue = "30") Integer durationMinutes) { | |||
| try { | |||
| ipSecurityService.addToBlacklist(ip, durationMinutes); | |||
| return Result.ok("IP " + ip + " 已成功加入黑名单"); | |||
| } catch (Exception e) { | |||
| log.error("添加IP到黑名单失败", e); | |||
| return Result.error("添加IP到黑名单失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "从黑名单移除IP") | |||
| @ApiOperation(value = "从黑名单移除IP", notes = "从黑名单中移除指定IP地址") | |||
| @DeleteMapping("/blacklist/remove") | |||
| public Result<String> removeFromBlacklist(@ApiParam(value = "IP地址", required = true) @RequestParam String ip) { | |||
| try { | |||
| ipSecurityService.removeFromBlacklist(ip); | |||
| return Result.ok("IP " + ip + " 已从黑名单中移除"); | |||
| } catch (Exception e) { | |||
| log.error("从黑名单移除IP失败", e); | |||
| return Result.error("从黑名单移除IP失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "添加IP到白名单") | |||
| @ApiOperation(value = "添加IP到白名单", notes = "将IP地址加入白名单,跳过访问限制") | |||
| @PostMapping("/whitelist/add") | |||
| public Result<String> addToWhitelist(@ApiParam(value = "IP地址", required = true) @RequestParam String ip) { | |||
| try { | |||
| ipSecurityService.addToWhitelist(ip); | |||
| return Result.ok("IP " + ip + " 已成功加入白名单"); | |||
| } catch (Exception e) { | |||
| log.error("添加IP到白名单失败", e); | |||
| return Result.error("添加IP到白名单失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "从白名单移除IP") | |||
| @ApiOperation(value = "从白名单移除IP", notes = "从白名单中移除指定IP地址") | |||
| @DeleteMapping("/whitelist/remove") | |||
| public Result<String> removeFromWhitelist(@ApiParam(value = "IP地址", required = true) @RequestParam String ip) { | |||
| try { | |||
| ipSecurityService.removeFromWhitelist(ip); | |||
| return Result.ok("IP " + ip + " 已从白名单中移除"); | |||
| } catch (Exception e) { | |||
| log.error("从白名单移除IP失败", e); | |||
| return Result.error("从白名单移除IP失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "获取IP访问统计") | |||
| @ApiOperation(value = "获取IP访问统计", notes = "获取指定IP的访问统计信息") | |||
| @GetMapping("/stats") | |||
| public Result<IpSecurityService.IpAccessStats> getIpAccessStats(@ApiParam(value = "IP地址", required = true) @RequestParam String ip) { | |||
| try { | |||
| IpSecurityService.IpAccessStats stats = ipSecurityService.getIpAccessStats(ip); | |||
| return Result.ok(stats); | |||
| } catch (Exception e) { | |||
| log.error("获取IP访问统计失败", e); | |||
| return Result.error("获取IP访问统计失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "获取当前IP访问统计") | |||
| @ApiOperation(value = "获取当前IP访问统计", notes = "获取当前请求IP的访问统计信息") | |||
| @GetMapping("/current-stats") | |||
| public Result<IpSecurityService.IpAccessStats> getCurrentIpAccessStats(HttpServletRequest request) { | |||
| try { | |||
| String clientIp = getClientIpAddress(request); | |||
| IpSecurityService.IpAccessStats stats = ipSecurityService.getIpAccessStats(clientIp); | |||
| return Result.ok(stats); | |||
| } catch (Exception e) { | |||
| log.error("获取当前IP访问统计失败", e); | |||
| return Result.error("获取当前IP访问统计失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| @AutoLog(value = "清除IP访问记录") | |||
| @ApiOperation(value = "清除IP访问记录", notes = "清除指定IP的所有访问记录") | |||
| @DeleteMapping("/clear-records") | |||
| public Result<String> clearIpAccessRecords(@ApiParam(value = "IP地址", required = true) @RequestParam String ip) { | |||
| try { | |||
| ipSecurityService.clearIpAccessRecords(ip); | |||
| return Result.ok("IP " + ip + " 的访问记录已清除"); | |||
| } catch (Exception e) { | |||
| log.error("清除IP访问记录失败", e); | |||
| return Result.error("清除IP访问记录失败: " + e.getMessage()); | |||
| } | |||
| } | |||
| /** | |||
| * 获取客户端真实IP地址 | |||
| */ | |||
| private String getClientIpAddress(HttpServletRequest request) { | |||
| String xForwardedFor = request.getHeader("X-Forwarded-For"); | |||
| if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) { | |||
| return xForwardedFor.split(",")[0].trim(); | |||
| } | |||
| String xRealIp = request.getHeader("X-Real-IP"); | |||
| if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) { | |||
| return xRealIp; | |||
| } | |||
| String proxyClientIp = request.getHeader("Proxy-Client-IP"); | |||
| if (proxyClientIp != null && !proxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(proxyClientIp)) { | |||
| return proxyClientIp; | |||
| } | |||
| String wlProxyClientIp = request.getHeader("WL-Proxy-Client-IP"); | |||
| if (wlProxyClientIp != null && !wlProxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(wlProxyClientIp)) { | |||
| return wlProxyClientIp; | |||
| } | |||
| return request.getRemoteAddr(); | |||
| } | |||
| } | |||
| @ -0,0 +1,192 @@ | |||
| package org.jeecg.modules.system.security; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Component; | |||
| import org.springframework.web.servlet.HandlerInterceptor; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * IP访问限制拦截器 | |||
| * 用于防止恶意攻击,限制单个IP的访问频率 | |||
| * | |||
| * @author system | |||
| * @date 2024 | |||
| */ | |||
| @Slf4j | |||
| @Component | |||
| public class IpAccessLimitInterceptor implements HandlerInterceptor { | |||
| @Autowired | |||
| private RedisTemplate<String, Object> redisTemplate; | |||
| // Redis key前缀 | |||
| private static final String IP_ACCESS_COUNT_KEY = "ip_access_count:"; | |||
| private static final String IP_BLACKLIST_KEY = "ip_blacklist:"; | |||
| private static final String IP_REQUEST_TIMES_KEY = "ip_request_times:"; | |||
| // 配置参数 | |||
| private static final int MAX_REQUESTS_PER_MINUTE = 120; // 每分钟最大请求数 | |||
| private static final int MAX_REQUESTS_PER_SECOND = 15; // 每秒最大请求数 | |||
| private static final int BLACKLIST_DURATION_MINUTES = 30; // 黑名单持续时间(分钟) | |||
| private static final int VIOLATION_THRESHOLD = 3; // 违规次数阈值 | |||
| @Override | |||
| public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | |||
| String clientIp = getClientIpAddress(request); | |||
| // 检查是否在黑名单中 | |||
| if (isInBlacklist(clientIp)) { | |||
| log.warn("IP {} 在黑名单中,拒绝访问", clientIp); | |||
| sendErrorResponse(response, "IP已被禁止访问"); | |||
| return false; | |||
| } | |||
| // 检查是否为白名单IP(可以跳过限制) | |||
| if (isWhitelistIp(clientIp)) { | |||
| return true; | |||
| } | |||
| // 检查访问频率 | |||
| if (!checkAccessLimit(clientIp)) { | |||
| log.warn("IP {} 访问频率过高,加入黑名单", clientIp); | |||
| addToBlacklist(clientIp); | |||
| sendErrorResponse(response, "访问频率过高,IP已被暂时禁止"); | |||
| return false; | |||
| } | |||
| log.info("IP {} 访问频率正常,继续处理", clientIp); | |||
| return true; | |||
| } | |||
| /** | |||
| * 获取客户端真实IP地址 | |||
| */ | |||
| private String getClientIpAddress(HttpServletRequest request) { | |||
| String xForwardedFor = request.getHeader("X-Forwarded-For"); | |||
| if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) { | |||
| return xForwardedFor.split(",")[0].trim(); | |||
| } | |||
| String xRealIp = request.getHeader("X-Real-IP"); | |||
| if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) { | |||
| return xRealIp; | |||
| } | |||
| String proxyClientIp = request.getHeader("Proxy-Client-IP"); | |||
| if (proxyClientIp != null && !proxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(proxyClientIp)) { | |||
| return proxyClientIp; | |||
| } | |||
| String wlProxyClientIp = request.getHeader("WL-Proxy-Client-IP"); | |||
| if (wlProxyClientIp != null && !wlProxyClientIp.isEmpty() && !"unknown".equalsIgnoreCase(wlProxyClientIp)) { | |||
| return wlProxyClientIp; | |||
| } | |||
| return request.getRemoteAddr(); | |||
| } | |||
| /** | |||
| * 检查IP是否在黑名单中 | |||
| */ | |||
| private boolean isInBlacklist(String ip) { | |||
| String key = IP_BLACKLIST_KEY + ip; | |||
| return redisTemplate.hasKey(key); | |||
| } | |||
| /** | |||
| * 检查是否为白名单IP | |||
| */ | |||
| private boolean isWhitelistIp(String ip) { | |||
| // 本地IP和内网IP跳过检查 | |||
| return ip.equals("127.0.0.1") || | |||
| ip.equals("localhost") || | |||
| ip.startsWith("192.168.") || | |||
| ip.startsWith("10.") || | |||
| ip.startsWith("172."); | |||
| } | |||
| /** | |||
| * 检查访问限制 | |||
| */ | |||
| private boolean checkAccessLimit(String ip) { | |||
| long currentTime = System.currentTimeMillis(); | |||
| long currentSecond = currentTime / 1000; | |||
| long currentMinute = currentTime / 60000; | |||
| // 检查每秒请求数 | |||
| String secondKey = IP_ACCESS_COUNT_KEY + ip + ":second:" + currentSecond; | |||
| Integer secondCount = (Integer) redisTemplate.opsForValue().get(secondKey); | |||
| if (secondCount == null) { | |||
| secondCount = 0; | |||
| } | |||
| if (secondCount >= MAX_REQUESTS_PER_SECOND) { | |||
| recordViolation(ip); | |||
| return false; | |||
| } | |||
| // 检查每分钟请求数 | |||
| String minuteKey = IP_ACCESS_COUNT_KEY + ip + ":minute:" + currentMinute; | |||
| Integer minuteCount = (Integer) redisTemplate.opsForValue().get(minuteKey); | |||
| if (minuteCount == null) { | |||
| minuteCount = 0; | |||
| } | |||
| if (minuteCount >= MAX_REQUESTS_PER_MINUTE) { | |||
| recordViolation(ip); | |||
| return false; | |||
| } | |||
| // 更新计数器 | |||
| redisTemplate.opsForValue().increment(secondKey); | |||
| redisTemplate.expire(secondKey, 2, TimeUnit.SECONDS); | |||
| redisTemplate.opsForValue().increment(minuteKey); | |||
| redisTemplate.expire(minuteKey, 2, TimeUnit.MINUTES); | |||
| return true; | |||
| } | |||
| /** | |||
| * 记录违规行为 | |||
| */ | |||
| private void recordViolation(String ip) { | |||
| String violationKey = "ip_violation:" + ip; | |||
| Integer violationCount = (Integer) redisTemplate.opsForValue().get(violationKey); | |||
| if (violationCount == null) { | |||
| violationCount = 0; | |||
| } | |||
| violationCount++; | |||
| redisTemplate.opsForValue().set(violationKey, violationCount, 1, TimeUnit.HOURS); | |||
| // 如果违规次数达到阈值,加入黑名单 | |||
| if (violationCount >= VIOLATION_THRESHOLD) { | |||
| addToBlacklist(ip); | |||
| } | |||
| } | |||
| /** | |||
| * 将IP加入黑名单 | |||
| */ | |||
| private void addToBlacklist(String ip) { | |||
| String key = IP_BLACKLIST_KEY + ip; | |||
| redisTemplate.opsForValue().set(key, System.currentTimeMillis(), BLACKLIST_DURATION_MINUTES, TimeUnit.MINUTES); | |||
| log.warn("IP {} 已被加入黑名单,持续时间: {} 分钟", ip, BLACKLIST_DURATION_MINUTES); | |||
| } | |||
| /** | |||
| * 发送错误响应 | |||
| */ | |||
| private void sendErrorResponse(HttpServletResponse response, String message) throws IOException { | |||
| response.setStatus(HttpServletResponse.SC_FORBIDDEN); | |||
| response.setContentType("application/json;charset=UTF-8"); | |||
| response.getWriter().write("{\"success\":false,\"message\":\"" + message + "\",\"code\":403}"); | |||
| } | |||
| } | |||
| @ -0,0 +1,211 @@ | |||
| package org.jeecg.modules.system.security; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * IP安全服务 | |||
| * 提供IP黑名单、白名单管理功能 | |||
| * | |||
| * @author system | |||
| * @date 2024 | |||
| */ | |||
| @Slf4j | |||
| @Service | |||
| public class IpSecurityService { | |||
| @Autowired | |||
| private RedisTemplate<String, Object> redisTemplate; | |||
| private static final String IP_BLACKLIST_KEY = "ip_blacklist:"; | |||
| private static final String IP_WHITELIST_KEY = "ip_whitelist:"; | |||
| private static final String IP_ACCESS_COUNT_KEY = "ip_access_count:"; | |||
| /** | |||
| * 手动添加IP到黑名单 | |||
| */ | |||
| public void addToBlacklist(String ip, int durationMinutes) { | |||
| String key = IP_BLACKLIST_KEY + ip; | |||
| redisTemplate.opsForValue().set(key, System.currentTimeMillis(), durationMinutes, TimeUnit.MINUTES); | |||
| log.info("手动将IP {} 加入黑名单,持续时间: {} 分钟", ip, durationMinutes); | |||
| } | |||
| /** | |||
| * 从黑名单中移除IP | |||
| */ | |||
| public void removeFromBlacklist(String ip) { | |||
| String key = IP_BLACKLIST_KEY + ip; | |||
| redisTemplate.delete(key); | |||
| log.info("从黑名单中移除IP: {}", ip); | |||
| } | |||
| /** | |||
| * 添加IP到白名单 | |||
| */ | |||
| public void addToWhitelist(String ip) { | |||
| String key = IP_WHITELIST_KEY + ip; | |||
| redisTemplate.opsForValue().set(key, System.currentTimeMillis()); | |||
| log.info("将IP {} 加入白名单", ip); | |||
| } | |||
| /** | |||
| * 从白名单中移除IP | |||
| */ | |||
| public void removeFromWhitelist(String ip) { | |||
| String key = IP_WHITELIST_KEY + ip; | |||
| redisTemplate.delete(key); | |||
| log.info("从白名单中移除IP: {}", ip); | |||
| } | |||
| /** | |||
| * 检查IP是否在黑名单中 | |||
| */ | |||
| public boolean isInBlacklist(String ip) { | |||
| String key = IP_BLACKLIST_KEY + ip; | |||
| return redisTemplate.hasKey(key); | |||
| } | |||
| /** | |||
| * 检查IP是否在白名单中 | |||
| */ | |||
| public boolean isInWhitelist(String ip) { | |||
| String key = IP_WHITELIST_KEY + ip; | |||
| return redisTemplate.hasKey(key); | |||
| } | |||
| /** | |||
| * 获取所有黑名单IP | |||
| */ | |||
| public List<IpInfo> getBlacklistIps() { | |||
| Set<String> keys = redisTemplate.keys(IP_BLACKLIST_KEY + "*"); | |||
| List<IpInfo> blacklistIps = new ArrayList<>(); | |||
| if (keys != null) { | |||
| for (String key : keys) { | |||
| String ip = key.replace(IP_BLACKLIST_KEY, ""); | |||
| Long addTime = (Long) redisTemplate.opsForValue().get(key); | |||
| Long ttl = redisTemplate.getExpire(key); | |||
| IpInfo ipInfo = new IpInfo(); | |||
| ipInfo.setIp(ip); | |||
| ipInfo.setAddTime(addTime); | |||
| ipInfo.setTtl(ttl); | |||
| ipInfo.setType("blacklist"); | |||
| blacklistIps.add(ipInfo); | |||
| } | |||
| } | |||
| return blacklistIps; | |||
| } | |||
| /** | |||
| * 获取所有白名单IP | |||
| */ | |||
| public List<IpInfo> getWhitelistIps() { | |||
| Set<String> keys = redisTemplate.keys(IP_WHITELIST_KEY + "*"); | |||
| List<IpInfo> whitelistIps = new ArrayList<>(); | |||
| if (keys != null) { | |||
| for (String key : keys) { | |||
| String ip = key.replace(IP_WHITELIST_KEY, ""); | |||
| Long addTime = (Long) redisTemplate.opsForValue().get(key); | |||
| IpInfo ipInfo = new IpInfo(); | |||
| ipInfo.setIp(ip); | |||
| ipInfo.setAddTime(addTime); | |||
| ipInfo.setTtl(-1L); // 白名单永不过期 | |||
| ipInfo.setType("whitelist"); | |||
| whitelistIps.add(ipInfo); | |||
| } | |||
| } | |||
| return whitelistIps; | |||
| } | |||
| /** | |||
| * 获取IP访问统计信息 | |||
| */ | |||
| public IpAccessStats getIpAccessStats(String ip) { | |||
| long currentTime = System.currentTimeMillis(); | |||
| long currentSecond = currentTime / 1000; | |||
| long currentMinute = currentTime / 60000; | |||
| String secondKey = IP_ACCESS_COUNT_KEY + ip + ":second:" + currentSecond; | |||
| String minuteKey = IP_ACCESS_COUNT_KEY + ip + ":minute:" + currentMinute; | |||
| Integer secondCount = (Integer) redisTemplate.opsForValue().get(secondKey); | |||
| Integer minuteCount = (Integer) redisTemplate.opsForValue().get(minuteKey); | |||
| IpAccessStats stats = new IpAccessStats(); | |||
| stats.setIp(ip); | |||
| stats.setCurrentSecondCount(secondCount != null ? secondCount : 0); | |||
| stats.setCurrentMinuteCount(minuteCount != null ? minuteCount : 0); | |||
| stats.setInBlacklist(isInBlacklist(ip)); | |||
| stats.setInWhitelist(isInWhitelist(ip)); | |||
| return stats; | |||
| } | |||
| /** | |||
| * 清除IP的所有访问记录 | |||
| */ | |||
| public void clearIpAccessRecords(String ip) { | |||
| Set<String> keys = redisTemplate.keys(IP_ACCESS_COUNT_KEY + ip + "*"); | |||
| if (keys != null && !keys.isEmpty()) { | |||
| redisTemplate.delete(keys); | |||
| log.info("清除IP {} 的访问记录", ip); | |||
| } | |||
| } | |||
| /** | |||
| * IP信息实体类 | |||
| */ | |||
| public static class IpInfo { | |||
| private String ip; | |||
| private Long addTime; | |||
| private Long ttl; | |||
| private String type; | |||
| // getters and setters | |||
| public String getIp() { return ip; } | |||
| public void setIp(String ip) { this.ip = ip; } | |||
| public Long getAddTime() { return addTime; } | |||
| public void setAddTime(Long addTime) { this.addTime = addTime; } | |||
| public Long getTtl() { return ttl; } | |||
| public void setTtl(Long ttl) { this.ttl = ttl; } | |||
| public String getType() { return type; } | |||
| public void setType(String type) { this.type = type; } | |||
| } | |||
| /** | |||
| * IP访问统计实体类 | |||
| */ | |||
| public static class IpAccessStats { | |||
| private String ip; | |||
| private Integer currentSecondCount; | |||
| private Integer currentMinuteCount; | |||
| private Boolean inBlacklist; | |||
| private Boolean inWhitelist; | |||
| // getters and setters | |||
| public String getIp() { return ip; } | |||
| public void setIp(String ip) { this.ip = ip; } | |||
| public Integer getCurrentSecondCount() { return currentSecondCount; } | |||
| public void setCurrentSecondCount(Integer currentSecondCount) { this.currentSecondCount = currentSecondCount; } | |||
| public Integer getCurrentMinuteCount() { return currentMinuteCount; } | |||
| public void setCurrentMinuteCount(Integer currentMinuteCount) { this.currentMinuteCount = currentMinuteCount; } | |||
| public Boolean getInBlacklist() { return inBlacklist; } | |||
| public void setInBlacklist(Boolean inBlacklist) { this.inBlacklist = inBlacklist; } | |||
| public Boolean getInWhitelist() { return inWhitelist; } | |||
| public void setInWhitelist(Boolean inWhitelist) { this.inWhitelist = inWhitelist; } | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| package org.jeecg.modules.system.security; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | |||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||
| /** | |||
| * Web安全配置 | |||
| * 注册IP访问限制拦截器 | |||
| * | |||
| * @author system | |||
| * @date 2024 | |||
| */ | |||
| @Configuration | |||
| public class WebSecurityConfig implements WebMvcConfigurer { | |||
| @Autowired | |||
| private IpAccessLimitInterceptor ipAccessLimitInterceptor; | |||
| @Override | |||
| public void addInterceptors(InterceptorRegistry registry) { | |||
| registry.addInterceptor(ipAccessLimitInterceptor) | |||
| .addPathPatterns("/**") // 拦截所有请求 | |||
| .excludePathPatterns( | |||
| "/sys/login", // 排除登录接口 | |||
| "/sys/logout", // 排除登出接口 | |||
| "/sys/randomImage", // 排除验证码接口 | |||
| "/sys/checkCaptcha", // 排除验证码校验接口 | |||
| "/sys/ip/manage/**", // 排除IP管理接口(避免管理员被锁定) | |||
| "/error", // 排除错误页面 | |||
| "/favicon.ico", // 排除图标 | |||
| "/static/**", // 排除静态资源 | |||
| "/public/**", // 排除公共资源 | |||
| "/actuator/**" // 排除监控端点 | |||
| ) | |||
| .order(1); // 设置拦截器优先级 | |||
| } | |||
| } | |||