Skip to content

pingxin403/floor-drain-spring-boot-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

floor-drain-spring-boot-starter

floor-drain是一款Web防护工具

JDK

流程

流程图

快速开始

添加依赖

<dependency>
    <groupId>com.github.hanyunpeng0521</groupId>
    <artifactId>floor-drain-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

相关配置

# 连续访问最高阀值,超过该值则认定为恶意操作的IP。单位:次 默认为20
floordrain.limit.access.threshold=20
# 间隔时间,在该时间内如果访问次数大于阀值,则记录为恶意IP,否则视为正常访问。单位:毫秒(ms),默认为 5秒
floordrain.limit.access.interval=5000
# 当检测到恶意访问时,对恶意访问的ip进行限制的时间。单位:毫秒(ms),默认为 1分钟
floordrain.limit.access.limitedTime=60000
# 黑名单存在的时间,在单位时间内用户访问受限的次数累加。单位:毫秒(ms),默认为 1个月
floordrain.limit.access.blacklistTime=2592000000
# 缓存类型,默认为map存储,可选值(map、redis)
floordrain.limit.access.type=map
  1. map存储是使用ConcurrentHashMap将数据存储在内存。
  2. Redis存储需要配置Redis。参考:https://pingxin0521.gitee.io/px_blog/2019/06/30/Java-SpringBoot-1-4-1/#示例
    # Redis数据库索引(默认为0)
    spring.redis.database=0  
    # Redis服务器地址
    spring.redis.host=localhost
    # Redis服务器连接端口
    spring.redis.port=6379  
    # Redis服务器连接密码(默认为空)
    spring.redis.password=

开启Braum

在启动类上添加@EnableFloorDrainConfiguration注解

@SpringBootApplication
@EnableFloorDrainConfiguration
public class FloorDrainSpringBootTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(FloorDrainSpringBootTestApplication.class, args);
    }

}

返回值

正常
{
	"code": 1,
	"msg": "[127.0.0.1]在5000毫秒内已连续发起 1 次请求",
	"expire": 0,
	"limitCount": 0,
	"accessInfo": {
		"ip": "127.0.0.1",
		"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36 OPR/64.0.3417.61",
		"referer": null,
		"requestUrl": "http://127.0.0.1:8080/",
		"params": ""
	}
}
被限制
{
	"code": 0,
	"msg": "[127.0.0.1]涉嫌恶意访问已被临时限制!共被限制过[1]次,本次剩余限制时间:60000 ms",
	"expire": 60000,
	"limitCount": 1,
	"accessInfo": {
		"ip": "127.0.0.1",
		"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36 OPR/64.0.3417.61",
		"referer": null,
		"requestUrl": "http://127.0.0.1:8080/",
		"params": ""
	}
}
字段 释义
code 响应码(1:正常,0:受限制)
msg 返回内容
expire 当请求被限制时该值不为0,表示为被限制的剩余时间,单位毫秒
limitCount 当请求被限制时该值不为0,表示为被限制的次数
accessInfo 本次发起请求的内容

accessInfo字段

字段 释义
ip 当前访问IP
ua 当前用户的UA
referer 请求来源
requestUrl 当前请求的地址
params 当前请求的参数

使用示例

  1. 修改配置文件
     # 连续访问最高阀值,超过该值则认定为恶意操作的IP。单位:次 默认为20
     floordrain.limit.access.threshold=2
     # 间隔时间,在该时间内如果访问次数大于阀值,则记录为恶意IP,否则视为正常访问。单位:毫秒(ms),默认为 5秒
     floordrain.limit.access.interval=2000
     # 当检测到恶意访问时,对恶意访问的ip进行限制的时间。单位:毫秒(ms),默认为 1分钟
     floordrain.limit.access.limitedTime=3000
     # 黑名单存在的时间,在单位时间内用户访问受限的次数累加。单位:毫秒(ms),默认为 1个月
     floordrain.limit.access.blacklistTime=2592000000
     # 缓存类型,默认为map存储,可选值(map、redis)
     floordrain.limit.access.type=map
    
  2. 在controller中处理
    @RestController
    public class FloorDrainController {
    
        @Autowired
        FloorDrainProcessor processor;
        @Autowired
        HttpServletRequest request;
    
        @RequestMapping("/")
        public Object index() {
            FloorDrainResponse r = processor.process(request);
            if (r.getCode() == CommonConst.ERROR) {
                return "你已涉嫌恶意访问被临时禁止,请文明上网";
            }
            return "Hello world!";
        }
    }
  3. 在拦截器中使用
     @Component
     public class FloorDrainIntercepter extends HandlerInterceptorAdapter {
         private static final Logger log = LoggerFactory.getLogger(FloorDrainIntercepter.class);
         private static final int SUCCESS = 1;
         private static List<String> msgList = new ArrayList<>();
     
         static {
             msgList.add("Wow...您太冲动了,先喝杯咖啡冷静下。");
             msgList.add("Wow...一杯不够?那再来一杯。");
             msgList.add("还不够?再来一杯!");
             msgList.add("你就不怕被撑死么?");
             msgList.add("古恩吧,不接你这种客了");
             msgList.add("古恩!");
         }
     
         @Autowired
         private FloorDrainProcessor processor;
     
         @Override
         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
             FloorDrainResponse r = processor.process(request);
             if (r.getCode() == SUCCESS) {
                 return true;
             }
             String msg = r.getLimitCount() > msgList.size() ? msgList.get(msgList.size() - 1) : msgList.get(r.getLimitCount() - 1);
             log.info(msg);
             response.setCharacterEncoding("UTF-8");
             response.setContentType("text/html;charset=utf-8");
             PrintWriter writer = response.getWriter();
             writer.write(msg);
             writer.flush();
             writer.close();
             return false;
         }
     }
    在config中加入拦截器
    @Configuration
    public class WebConfig extends WebMvcConfigurationSupport {
    
        @Bean
        public FloorDrainIntercepter getSecurityInterceptor() {
            return new FloorDrainIntercepter();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            InterceptorRegistration addInterceptor = registry.addInterceptor(getSecurityInterceptor());
    
            // 排除配置
            addInterceptor.excludePathPatterns("/403");
            // 拦截配置
            addInterceptor.addPathPatterns("/**");
        }
    }