# bb-anti-reptile
**Repository Path**: RemoteControl/bb-anti-reptile
## Basic Information
- **Project Name**: bb-anti-reptile
- **Description**: 积木防爬组件,目标是自动化收集用户访问率以达到控制异常访问。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 1
- **Created**: 2024-03-21
- **Last Updated**: 2025-10-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# bb-anti-reptile
### 介绍
积木防爬组件,一款目标开箱即可用反扒组件,以达到控制异常访问。
包括基于ip、和ua的简单控制,以及添加了ip-plus-rule和user-rule两种规则,基于用户的访问日志(Plumelog-me等)以分析ip和用户的访问规则自动添加访问规则,以限流/验证码/黑名单/告警通知限制访问。
### 系统要求
- 基于 spring-boot 开发(spring-boot2.x)
- 需要 redisson
### 模块说明
#### 1. bb-anti-reptile-core 反扒核心模块,实现了4中规则,以及自带默认方案(最简单方案):比如限流,响应方案、存储方案
- 四种方案:
+ 基于ua,通过User-Agent字符串 控制用户授权访问,常用几种规则:allowedLinux、allowedMobile、allowedPc、allowedIot、allowedProxy
+ 基于ip,设置白名单/黑名单ip,以及设置允许ip通过的流量,来控制ip授权访问(难点在于怎么设置ip的限流数值)
+ 基于ip-plus(仅限非登录), 同样可以设置白名单/黑名单ip,流量限制 基于ip/用户 的访问规则以精准区分流量(好处2个,1、无需设置流量值 2、各个ip将更精准),目前数据分析有2种块(集成Plumelog-me(已完成)、自行分析后自行写入db《bb-anti-reptile-data-db》)
+ 基于user(仅限登录),同样限流,限制用户的访问规则以精准区分流量,目前数据分析有2块(集成Plumelog-me(已完成)、自行分析后写入db《bb-anti-reptile-data-db》)
+ 基于平台限流/告警,基于url限流/告警(和以上差异为,一旦限流本规则仅限控制此接口,其他接口不受影响,其他规则则全部限制接口都会受影响)
- 4种限流结果:
+ lock-type=1,只是限流
+ lock-type=2,限流且加入可解除的黑名单(黑名单时间建议设置比较短)
+ lock-type=3,限流且加入不可解除的黑名单(黑名单时间建议设置比较长)
+ lock-type=9,告警
#### 2. bb-anti-reptile-rateLimiter-redisson 同步限流方案,可以自行实现你需要的限流插件(限流)
#### 3. bb-anti-reptile-data-esstat Plumelog-me 日志分析器插件(日志分析-未优化,含bb-anti-reptile-data-db)
#### 4. bb-anti-reptile-es es配置插件
#### 5. bb-anti-reptile-data-db db存储(存储方案-mysql)
#### 6. bb-anti-reptile-springboot-starter 应用启动器-目前只能在非网关启动,启动 SpringMVC拦截器 对请求进行过滤
#### 7. bb-anti-reptile-captcha 验证码插件,支持验证码限流场景下(仅限验证码限流),用户通过验证码解锁(ip限流解ip,user限流解user)
#### 8. bb-anti-reptile-mailalarm 邮件告警,lock-type=9模式下配置邮件属性,以通知管理员,否则只告警无通知,可以根据此定义自己的通知渠道
### 使用说明
#### 1. 添加maven依赖(目前未添加到公用maven库,请自行打包到私服或者 mvn install 至本地)
引入依赖条件:
- mvn install 至本地
- deploy 至私服
- 使用作者的gitee 版本库,pom添加如下
```yaml
jin-gitee-maven
https://gitee.com/RemoteControl/maven-repository/raw/master
```
```xml
com.bblocks.common
bb-anti-reptile-springboot-starter
1.0.1-SNAPSHOT
com.bblocks.common
bb-anti-reptile-rateLimiter-redisson
1.0.1-SNAPSHOT
com.bblocks.common
bb-anti-reptile-data-db
1.0.1-SNAPSHOT
```
#### 2. 配置redisson
#### 3. 配置以启动(全部参数如下)
```properties
#限流/反爬配置
anti:
reptile:
#全局开关
enabled: true
#启用全局拦截
global-filter-mode: true
#非全局拦截下,反扒接口(支持正则表达式匹配(如:^/xx/.*$)
include-urls: /abc/1,/abc/2
ua-rule:
enabled: false
ip-rule:
#ip限流(可以用,但不好用,不知道配置数字多少,且ip接口差异太大)
enabled: false
#时间窗口(ms)
expiration-time: 5000
#时间窗口限制量(默认无-不限制)
request-max-size: 10
#锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁)
lock-type: 1
#命中规则后,锁定期限(s)-默认1天,验证码建议30秒
lock-expire: 30
#限制后响应
lock-response: '{"code":0,"msg":"限流!","serviceTips":"限流","sucFlag":false}'
ip-plus-rule:
enabled: true
# hea的token-key(默认Authorization)
token-key: Authorization
#时间窗口(ms)
expiration-time: 5000
#时间窗口限制量(默认值-仅在url无参数的时候生效-不配置不生效)
request-max-size: 10
#锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁)
lock-type: 2
#命中规则后,锁定期限(s)-默认1天,验证码建议10分钟
lock-expire: 600
#最大值系数(url的max*此系数=最终最大值)
multiplier: 100.0
#限制后响应
lock-response: '{ "code": 0,"msg": "限流验证码!","serviceTips": "限流验证码!","sucFlag": false }'
user-rule:
enabled: true
# hea的token-key(默认Authorization)
token-key: Authorization
#时间窗口(ms)
expiration-time: 5000
#时间窗口限制量(默认值-仅在url无参数的时候生效-不配置不生效)
request-max-size: 10
#锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁)
lock-type: 3
#最大值系数(url的max*此系数=最终最大值)
multiplier: 25.0
#限制后响应
lock-response: '{ "code": 0,"msg": "限流黑名单咯!","serviceTips": "限流黑名单咯!","sucFlag": false }'
#bb-anti-reptile-data-esstat 组件需要提取分析日志来源
es:
host: 127.0.0.1
port: 9200
username:
password:
#bb-anti-reptile-data-db 组件需要查询数据(sys_access_sum、sys_access_ip_sum)
db:
url: jdbc:mysql://127.0.0.1:33060/bb_admin?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
#bb-anti-reptile-data-db 同步数据用,db-》redis
sync:
#启动同步一次限流规则(建议不要启动-测试阶段可以)
sync-on-start: false
#每天同步时间(2点)
sync-time: 2
#统一的响应策略参数(ip-plus-rule/user-rule 特殊的响应策略,时间单位:s,1=限流,2=验证码限流,3=黑名单限流)
rule-result-params:
- lock-type: 1
lock-expire: 30
lock-response: '{"code":0,"msg":"限流!","serviceTips":"限流","sucFlag":false}'
- lock-type: 2
lock-expire: 600
lock-response: '{ "code": 0,"msg": "限流验证码!","serviceTips": "限流验证码!","sucFlag": false }'
- lock-type: 3
lock-expire: 86400
lock-response: '{ "code": 0,"msg": "限流黑名单咯!","serviceTips": "限流黑名单咯!","sucFlag": false }'
```
#### 4. bb-anti-reptile-data-db 需要连接db,请初始化 doc/bb-anti-reptile-plugin.sql 脚本至配置数据库
- db配置中的 rate_ip_limit_type、rate_user_limit_type、rate_plate_limit_type 比此规则中的lock-type优先级高
#### 5. 自行分析你的访问日志,提取:用户最大访问qps、平均qps,ip最大qps(非登录qps/ip/用户),ip平均qps(非登录qps/ip/用户),以及ip的用户数量,写入db以供 user-rule和ip-plus-rule使用
#### 6. 或者直接使用启用组件:bb-anti-reptile-data-esstat,集成Plumelog-me日志分析并写入db(每天启动时:sync.sync-time-1 启动),配置以及使用条件:
1. 配置:
```xml
com.bblocks.common
bb-anti-reptile-data-esstat
1.0.1-SNAPSHOT
```
```properties
#限流/反爬配置 日志分析
anti:
reptile:
esstat:
#es分组,分隔字符串
spitter-str: "&&&"
##分析数据超过7天,才最后产生限流规则(7天内只分析数据),默认:0(不启动)
stat-limit-day: 2
```
2. 使用条件(具体查询dsl见:bb-anti-reptile-plugin\bb-anti-reptile-data-esstat\src\main\resources\static\),目前为了查询接口上的用户信息查询都是走的应用服务器日志,未查询网关日志
- 含字段:USER_ID(以分析用户行为)
- 含字段:FROM(以区分服务内部调用-微服务用,目前分析的数据是来自网关的调用)
- 含字段:IP(以分析ip行为)
- 含字段:COST(以区分日志请求还是响应-目前都是分析请求)
- 含字段:URL(以分析请求qps)
- 具体dsl:
+ ip_day_users.json 分页统计ip的用户数量
+ ip_nologin_access.json 分页统计url-ip(未登录)请求
+ ip_nologin_access_qps.json 统计url-ip(未登录)请求,最大qps-单ip(以计算url ip平均qps)
+ user_access.json 分页统计url-userid请求
+ user_access_qps.json 统计url-userid请求最大qps-单人(以计算url人平均qps)
- Plumelog-me添加日志字段:
```java
MDC.put("USER_ID","用户ID。。。(可能无)");
MDC.put("FROM","来源。。。");
MDC.put("IP","ip、、、");
MDC.put("COST","耗时。。。");
MDC.put("URL","url...");
logger.info("扩展字段");
```
3. 如需定制es查询dsl(原则上是肯定需要修改的),请/doc/static/下 dsl修改后 static文件夹放入项目resource下即可
#### 7. 接口使用反扒三个方案:
1. 使用配置文件,启动全局过滤
```properties
anti.reptile.global-filter-mode: true
```
2. 使用配置文件,只开启具体接口过滤
```properties
anti.reptile.global-filter-mode: false
anti.reptile.include-urls: /xxx
```
3. 使用注解以启动
```properties
anti.reptile.global-filter-mode: false
```
```java
@AntiReptile
@GetMapping("/xxx")
public R hello() {
return R.ok("Hello,World!");
}
```
#### 8. 验证码限流后解锁
1. 添加依赖
```xml
com.bblocks.common
bb-anti-reptile-captcha
1.0.1
```
2. 提取验证码(当前段收到 验证码限流响应码时 调用此接口弹出验证窗口):post /antireptile/captcha/one,响应格式如下:
```json
{
"msg": "成功",
"data": {
"verKey": "fef703da-2528-4c51-882f-35af5850698a",
"image": "data:image/png;base64,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"
},
"code": 1
}
```
3. 验证验证码:post /antireptile/captcha/verify?verKey=xxx&verCode=xxx,验证通过即可解除 验证码限流提示
4. 其他属性配置:
```properties
#定义响应对象(可以不配置,以下的均为默认值)
anti.reptile.captcha.code-name: code
anti.reptile.captcha.msg-name: msg
anti.reptile.captcha.data-name: data
#定义成功的code值(一般0/1)
anti.reptile.captcha.code-suc: 1
#验证码有效期(分钟)
anti.reptile.captcha.timeout: 10
```
5. 其他需求参考模块:bb-anti-reptile-captcha,其他解锁如:黑名单解锁也参考:RuleActuator.reset(HttpServletRequest request, String realRequestUri, RuleResultEnum resetTypeLimit)
6. 固定配置的ip黑名单目前直接返回 黑名单限流同时不能解除
### 缺陷/待改进
1. 基于用户的拦截,目前拦截的是token,后续提供用户token转换user_id接口,以达到直接拦截user_id(已实现2024-04-02)
2. 后续再定制验证码方案,目前只是返回了错误码,需要开发定制验证码业务(已实现2024-04-17)
3. 基于Plumelog-me日志统计分析未完成,所以需要自行统计分析写入DB,bb-anti-reptile-data-db负责读取数据源(已实现2024-04-12)
4. 限流属于同步操作,会影响并发后期考虑使用异步限流,以提高性能(火焰分析主要耗时:黑名单验证、限流(大头))
5. 目前的starter 未实现gateway,但是还是感觉限流在gw上更合适,需要实现gw上starter
6. 支持特定策略,sys_access_sum.rate_limit_type 可以配置特定的响应策略(已实现2024-04-12)
7. 支持拦截回调,以记录用户黑名单信息,实现见:NoticeServiceImplDefault(已实现2024-04-16)
### 特技
1. 集成Plumelog-me,可以做到开箱使用,无需配置限流参数值,集成其他平台可以参考实现。
2. 基于统计分析,可以知道每个用户对每个接口的使用需求,按照此系数自动设定每个用户的qps,支持冗余(1、n秒 * qps以平滑,2、qps支持一定的放大系数 3、支持验证码限流,在超过值后允许用户解开验证码再次使用)
3. 基于统计分析,可以统计ip用户数量,以及以及带来的非登录访问qps,以此计算出一个用户会有多少非登录qps,最终得出每个ip限流量,支持冗余(1、n秒 * qps以平滑,2、qps支持一定的放大系数 3、支持验证码限流,再超过值后允许用户解开验证码再次使用)
4. 简单做了性能测试qps能达到:6000(组件添加前:28000)-10线程无业务(amd R5 24G内存),具体测试文件见doc/limit_after.png
### 参与贡献
1. 参考了kk-anti-reptile