mm_ip 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # mm_ip
2
+
3
+ [English](README_EN.md) | [中文](README.md)
4
+
5
+ 一个功能强大的IP管理模块,支持白名单、黑名单管理、IP请求频率监控、违规记录和持久化存储。
6
+
7
+ ## 功能特性
8
+
9
+ - ✅ **白名单管理** - 支持添加、删除、查询白名单IP
10
+ - ✅ **黑名单管理** - 支持添加、删除、查询黑名单IP,支持自动过期
11
+ - ✅ **IP请求频率监控** - 实时监控IP请求频率,防止高频访问
12
+ - ✅ **自动拉黑机制** - 支持高频访问自动拉黑和违规次数超限自动拉黑
13
+ - ✅ **违规记录系统** - 记录IP违规行为,支持违规次数统计和重置
14
+ - ✅ **持久化存储** - 支持数据分文件存储(白名单、黑名单、违规记录独立存储)
15
+ - ✅ **自动保存机制** - 支持定时自动保存和操作触发保存
16
+ - ✅ **重启数据恢复** - 支持重启后自动加载持久化数据
17
+ - ✅ **灵活配置** - 支持自定义各种阈值和参数
18
+
19
+ ## 安装
20
+
21
+ ```bash
22
+ npm install mm_ip
23
+ ```
24
+
25
+ ## 快速开始
26
+
27
+ ### 基本使用
28
+
29
+ ```javascript
30
+ const { Ip } = require('mm_ip');
31
+
32
+ // 创建IP管理实例
33
+ const ip_manager = new Ip();
34
+
35
+ // 设置日志器(可选)
36
+ ip_manager.setup(console);
37
+
38
+ // 添加白名单IP
39
+ ip_manager.addWhite('192.168.1.100');
40
+
41
+ // 添加黑名单IP
42
+ ip_manager.addBlack('10.0.0.100');
43
+
44
+ // 检查IP状态
45
+ console.log('192.168.1.100 在白名单:', ip_manager.isWhite('192.168.1.100'));
46
+ console.log('10.0.0.100 在黑名单:', ip_manager.isBlack('10.0.0.100'));
47
+
48
+ // 记录IP请求
49
+ console.log('192.168.1.100 请求结果:', ip_manager.record('192.168.1.100'));
50
+ ```
51
+
52
+ ### 持久化存储配置
53
+
54
+ ```javascript
55
+ // 创建带持久化配置的实例
56
+ const persistent_ip = new Ip({
57
+ dir: './cache/ip', // 存储目录
58
+ max_white: 1000, // 最大白名单数量
59
+ max_black: 1000 // 最大黑名单数量
60
+ });
61
+
62
+ // 添加数据后会自动保存到文件
63
+ persistent_ip.addWhite('192.168.1.101');
64
+ persistent_ip.addBlack('10.0.0.101');
65
+
66
+ // 重启后自动加载数据
67
+ const new_ip = new Ip({ dir: './cache/ip' });
68
+ console.log('重启后白名单数量:', new_ip.getAllWhite().length);
69
+ ```
70
+
71
+ ## API文档
72
+
73
+ ### 构造函数
74
+
75
+ ```javascript
76
+ new Ip(config)
77
+ ```
78
+
79
+ **配置参数 (config):**
80
+
81
+ | 参数 | 类型 | 默认值 | 描述 |
82
+ |------|------|--------|------|
83
+ | `max_white` | number | 1000 | 最大白名单数量 |
84
+ | `max_black` | number | 1000 | 最大黑名单数量 |
85
+ | `check_interval` | number | 60000 | 检查间隔(毫秒) |
86
+ | `max_req_per_min` | number | 100 | 每分钟最大请求数 |
87
+ | `auto_black_enable` | boolean | true | 启用自动高频拉黑 |
88
+ | `auto_black_threshold` | number | 50 | 自动拉黑阈值 |
89
+ | `auto_black_duration` | number | 3600000 | 自动拉黑持续时间(毫秒) |
90
+ | `violation_enable` | boolean | true | 启用违规记录 |
91
+ | `violation_max_count` | number | 10 | 最大违规次数 |
92
+ | `violation_reset_time` | number | 86400000 | 违规记录重置时间(毫秒) |
93
+ | `violation_auto_black` | boolean | true | 违规次数超限自动拉黑 |
94
+ | `dir` | string | './cache/ip' | 持久化存储目录 |
95
+
96
+ ### 主要方法
97
+
98
+ #### 白名单操作
99
+ - `addWhite(ip)` - 添加白名单IP
100
+ - `delWhite(ip)` - 删除白名单IP
101
+ - `isWhite(ip)` - 检查是否在白名单
102
+ - `getAllWhite()` - 获取所有白名单IP
103
+ - `clearWhite()` - 清空白名单
104
+
105
+ #### 黑名单操作
106
+ - `addBlack(ip)` - 添加黑名单IP
107
+ - `delBlack(ip)` - 删除黑名单IP
108
+ - `isBlack(ip)` - 检查是否在黑名单
109
+ - `getAllBlack()` - 获取所有黑名单IP
110
+ - `clearBlack()` - 清空黑名单
111
+ - `getBlackExpireTime(ip)` - 获取黑名单过期时间
112
+
113
+ #### IP请求记录
114
+ - `record(ip)` - 记录IP请求,返回是否允许访问
115
+ - `getReqCount(ip)` - 获取IP请求次数
116
+ - `getReqFreq(ip)` - 获取IP请求频率
117
+
118
+ #### 违规记录
119
+ - `recordViolation(ip, reason)` - 记录IP违规
120
+ - `getViolationCount(ip)` - 获取违规次数
121
+ - `resetViolation(ip)` - 重置违规记录
122
+ - `clearViolations()` - 清空所有违规记录
123
+ - `getAllViolations()` - 获取所有违规记录
124
+
125
+ #### 持久化存储
126
+ - `save()` - 手动保存数据
127
+ - `load()` - 手动加载数据
128
+ - `autoSave(interval)` - 开启自动保存
129
+ - `stopAutoSave()` - 停止自动保存
130
+
131
+ #### 综合操作
132
+ - `del(ip)` - 删除IP的所有记录
133
+ - `setup(logger)` - 设置日志器
134
+
135
+ ## 存储文件结构
136
+
137
+ 当启用持久化存储时,数据会分三个文件存储:
138
+
139
+ ```
140
+ cache/ip/
141
+ ├── white.json # 白名单数据
142
+ ├── black.json # 黑名单数据
143
+ └── violation.json # 违规记录数据
144
+ ```
145
+
146
+ 每个文件包含对应的数据数组和时间戳信息。
147
+
148
+ ## 测试
149
+
150
+ 运行测试用例:
151
+
152
+ ```bash
153
+ npm test
154
+ ```
155
+
156
+ 或直接运行:
157
+
158
+ ```bash
159
+ node test.js
160
+ ```
161
+
162
+ ## 许可证
163
+
164
+ ISC License
165
+
166
+ ## 作者
167
+
168
+ qww
169
+
170
+ ## 仓库地址
171
+
172
+ - Gitee: https://gitee.com/qiuwenwu91/mm_ip.git
173
+ - npm: https://www.npmjs.com/package/mm_ip
package/README_EN.md ADDED
@@ -0,0 +1,173 @@
1
+ # mm_ip
2
+
3
+ [English](README_EN.md) | [中文](README.md)
4
+
5
+ A powerful IP management module that supports whitelist, blacklist management, IP request frequency monitoring, violation records, and persistent storage.
6
+
7
+ ## Features
8
+
9
+ - ✅ **Whitelist Management** - Add, remove, and query whitelist IPs
10
+ - ✅ **Blacklist Management** - Add, remove, and query blacklist IPs with auto-expiration
11
+ - ✅ **IP Request Frequency Monitoring** - Real-time IP request frequency monitoring to prevent high-frequency access
12
+ - ✅ **Auto-Blacklist Mechanism** - Automatic blacklisting for high-frequency access and violation limit exceeding
13
+ - ✅ **Violation Record System** - Record IP violation behaviors with violation count statistics and reset
14
+ - ✅ **Persistent Storage** - Support for separate file storage (whitelist, blacklist, violation records stored independently)
15
+ - ✅ **Auto-Save Mechanism** - Support for timed auto-save and operation-triggered save
16
+ - ✅ **Data Recovery on Restart** - Automatic loading of persistent data after restart
17
+ - ✅ **Flexible Configuration** - Support for custom thresholds and parameters
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install mm_ip
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Basic Usage
28
+
29
+ ```javascript
30
+ const { Ip } = require('mm_ip');
31
+
32
+ // Create IP management instance
33
+ const ip_manager = new Ip();
34
+
35
+ // Setup logger (optional)
36
+ ip_manager.setup(console);
37
+
38
+ // Add whitelist IP
39
+ ip_manager.addWhite('192.168.1.100');
40
+
41
+ // Add blacklist IP
42
+ ip_manager.addBlack('10.0.0.100');
43
+
44
+ // Check IP status
45
+ console.log('192.168.1.100 in whitelist:', ip_manager.isWhite('192.168.1.100'));
46
+ console.log('10.0.0.100 in blacklist:', ip_manager.isBlack('10.0.0.100'));
47
+
48
+ // Record IP request
49
+ console.log('192.168.1.100 request result:', ip_manager.record('192.168.1.100'));
50
+ ```
51
+
52
+ ### Persistent Storage Configuration
53
+
54
+ ```javascript
55
+ // Create instance with persistent storage configuration
56
+ const persistent_ip = new Ip({
57
+ dir: './cache/ip', // Storage directory
58
+ max_white: 1000, // Maximum whitelist count
59
+ max_black: 1000 // Maximum blacklist count
60
+ });
61
+
62
+ // Data will be automatically saved after adding
63
+ persistent_ip.addWhite('192.168.1.101');
64
+ persistent_ip.addBlack('10.0.0.101');
65
+
66
+ // Auto-load data after restart
67
+ const new_ip = new Ip({ dir: './cache/ip' });
68
+ console.log('Whitelist count after restart:', new_ip.getAllWhite().length);
69
+ ```
70
+
71
+ ## API Documentation
72
+
73
+ ### Constructor
74
+
75
+ ```javascript
76
+ new Ip(config)
77
+ ```
78
+
79
+ **Configuration Parameters (config):**
80
+
81
+ | Parameter | Type | Default | Description |
82
+ |-----------|------|---------|-------------|
83
+ | `max_white` | number | 1000 | Maximum whitelist count |
84
+ | `max_black` | number | 1000 | Maximum blacklist count |
85
+ | `check_interval` | number | 60000 | Check interval (milliseconds) |
86
+ | `max_req_per_min` | number | 100 | Maximum requests per minute |
87
+ | `auto_black_enable` | boolean | true | Enable auto-blacklist for high frequency |
88
+ | `auto_black_threshold` | number | 50 | Auto-blacklist threshold |
89
+ | `auto_black_duration` | number | 3600000 | Auto-blacklist duration (milliseconds) |
90
+ | `violation_enable` | boolean | true | Enable violation records |
91
+ | `violation_max_count` | number | 10 | Maximum violation count |
92
+ | `violation_reset_time` | number | 86400000 | Violation record reset time (milliseconds) |
93
+ | `violation_auto_black` | boolean | true | Auto-blacklist when violation count exceeds limit |
94
+ | `dir` | string | './cache/ip' | Persistent storage directory |
95
+
96
+ ### Main Methods
97
+
98
+ #### Whitelist Operations
99
+ - `addWhite(ip)` - Add IP to whitelist
100
+ - `delWhite(ip)` - Remove IP from whitelist
101
+ - `isWhite(ip)` - Check if IP is in whitelist
102
+ - `getAllWhite()` - Get all whitelist IPs
103
+ - `clearWhite()` - Clear all whitelist IPs
104
+
105
+ #### Blacklist Operations
106
+ - `addBlack(ip)` - Add IP to blacklist
107
+ - `delBlack(ip)` - Remove IP from blacklist
108
+ - `isBlack(ip)` - Check if IP is in blacklist
109
+ - `getAllBlack()` - Get all blacklist IPs
110
+ - `clearBlack()` - Clear all blacklist IPs
111
+ - `getBlackExpireTime(ip)` - Get blacklist expiration time
112
+
113
+ #### IP Request Recording
114
+ - `record(ip)` - Record IP request, return whether access is allowed
115
+ - `getReqCount(ip)` - Get IP request count
116
+ - `getReqFreq(ip)` - Get IP request frequency
117
+
118
+ #### Violation Records
119
+ - `recordViolation(ip, reason)` - Record IP violation
120
+ - `getViolationCount(ip)` - Get violation count
121
+ - `resetViolation(ip)` - Reset violation record
122
+ - `clearViolations()` - Clear all violation records
123
+ - `getAllViolations()` - Get all violation records
124
+
125
+ #### Persistent Storage
126
+ - `save()` - Manually save data
127
+ - `load()` - Manually load data
128
+ - `autoSave(interval)` - Enable auto-save
129
+ - `stopAutoSave()` - Stop auto-save
130
+
131
+ #### Comprehensive Operations
132
+ - `del(ip)` - Delete all records for an IP
133
+ - `setup(logger)` - Setup logger
134
+
135
+ ## Storage File Structure
136
+
137
+ When persistent storage is enabled, data is stored in three separate files:
138
+
139
+ ```
140
+ cache/ip/
141
+ ├── white.json # Whitelist data
142
+ ├── black.json # Blacklist data
143
+ └── violation.json # Violation record data
144
+ ```
145
+
146
+ Each file contains corresponding data arrays and timestamp information.
147
+
148
+ ## Testing
149
+
150
+ Run test cases:
151
+
152
+ ```bash
153
+ npm test
154
+ ```
155
+
156
+ Or run directly:
157
+
158
+ ```bash
159
+ node test.js
160
+ ```
161
+
162
+ ## License
163
+
164
+ ISC License
165
+
166
+ ## Author
167
+
168
+ qww
169
+
170
+ ## Repository
171
+
172
+ - Gitee: https://gitee.com/qiuwenwu91/mm_ip.git
173
+ - npm: https://www.npmjs.com/package/mm_ip
@@ -0,0 +1,27 @@
1
+ {
2
+ "black": [
3
+ "192.168.100.2",
4
+ "192.168.200.1",
5
+ "192.168.200.2",
6
+ "192.168.200.3"
7
+ ],
8
+ "black_time": [
9
+ [
10
+ "172.16.0.2",
11
+ 1765261940971
12
+ ],
13
+ [
14
+ "192.168.100.2",
15
+ 1765262134846
16
+ ],
17
+ [
18
+ "192.168.200.2",
19
+ 1765262135900
20
+ ],
21
+ [
22
+ "192.168.200.3",
23
+ 1765262135908
24
+ ]
25
+ ],
26
+ "timestamp": 1765262142949
27
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "violation_count": [],
3
+ "violation_time": [],
4
+ "timestamp": 1765262142949
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "white": [],
3
+ "timestamp": 1765262142949
4
+ }
package/index.js CHANGED
@@ -25,7 +25,8 @@ class Ip {
25
25
  violation_enable: true, // 启用违规记录
26
26
  violation_max_count: 10, // 最大违规次数
27
27
  violation_reset_time: 86400000, // 违规记录重置时间(24小时)
28
- violation_auto_black: true // 违规次数超限自动拉黑
28
+ violation_auto_black: true, // 违规次数超限自动拉黑
29
+ dir: './cache/ip' // 持久化存储目录
29
30
  }, config || {});
30
31
 
31
32
  this._white = new Set();
@@ -36,6 +37,11 @@ class Ip {
36
37
  this._violation_count = new Map(); // 违规次数记录
37
38
  this._violation_time = new Map(); // 违规时间记录
38
39
  this._logger = $.log || console;
40
+
41
+ // 自动加载持久化数据
42
+ if (this._config.dir) {
43
+ this.load();
44
+ }
39
45
  }
40
46
  }
41
47
 
@@ -75,6 +81,12 @@ Ip.prototype.addWhite = function (ip) {
75
81
 
76
82
  this._white.add(ip);
77
83
  this.logger('info', '添加白名单IP:', ip);
84
+
85
+ // 自动保存到持久化存储
86
+ if (this._config.dir) {
87
+ this.save();
88
+ }
89
+
78
90
  return true;
79
91
  };
80
92
 
@@ -94,6 +106,12 @@ Ip.prototype.addBlack = function (ip) {
94
106
 
95
107
  this._black.add(ip);
96
108
  this.logger('info', '添加黑名单IP:', ip);
109
+
110
+ // 自动保存到持久化存储
111
+ if (this._config.dir) {
112
+ this.save();
113
+ }
114
+
97
115
  return true;
98
116
  };
99
117
 
@@ -109,6 +127,11 @@ Ip.prototype.delWhite = function (ip) {
109
127
  const result = this._white.delete(ip);
110
128
  if (result) {
111
129
  this.logger('info', '删除白名单IP:', ip);
130
+
131
+ // 自动保存到持久化存储
132
+ if (this._config.dir) {
133
+ this.save();
134
+ }
112
135
  }
113
136
  return result;
114
137
  };
@@ -125,6 +148,11 @@ Ip.prototype.delBlack = function (ip) {
125
148
  const result = this._black.delete(ip);
126
149
  if (result) {
127
150
  this.logger('info', '删除黑名单IP:', ip);
151
+
152
+ // 自动保存到持久化存储
153
+ if (this._config.dir) {
154
+ this.save();
155
+ }
128
156
  }
129
157
  return result;
130
158
  };
@@ -294,17 +322,27 @@ Ip.prototype.getAllReqIps = function () {
294
322
  /**
295
323
  * 清空白名单
296
324
  */
297
- Ip.prototype.clearWhite = function () {
325
+ Ip.prototype.clearWhite = function() {
298
326
  this._white.clear();
299
327
  this.logger('info', '清空白名单');
328
+
329
+ // 自动保存到持久化存储
330
+ if (this._config.dir) {
331
+ this.save();
332
+ }
300
333
  };
301
334
 
302
335
  /**
303
336
  * 清空黑名单
304
337
  */
305
- Ip.prototype.clearBlack = function () {
338
+ Ip.prototype.clearBlack = function() {
306
339
  this._black.clear();
307
340
  this.logger('info', '清空黑名单');
341
+
342
+ // 自动保存到持久化存储
343
+ if (this._config.dir) {
344
+ this.save();
345
+ }
308
346
  };
309
347
 
310
348
  /**
@@ -620,6 +658,194 @@ Ip.prototype.clearViolations = function() {
620
658
  this._violation_count.clear();
621
659
  this._violation_time.clear();
622
660
  this.logger('info', '清空所有违规记录');
661
+
662
+ // 自动保存到持久化存储
663
+ if (this._config.dir) {
664
+ this.save();
665
+ }
666
+ };
667
+
668
+ /**
669
+ * 保存IP数据到文件(持久化存储)
670
+ * @returns {boolean} 是否保存成功
671
+ */
672
+ Ip.prototype.save = function() {
673
+ try {
674
+ const fs = require('fs');
675
+ const path = require('path');
676
+
677
+ // 确保存储目录存在
678
+ const dir = this._config.dir;
679
+ dir.addDir();
680
+
681
+ // 分别保存不同数据到不同文件
682
+ const timestamp = Date.now();
683
+
684
+ // 保存白名单数据
685
+ const whiteData = {
686
+ white: this.getAllWhite(),
687
+ timestamp: timestamp
688
+ };
689
+ const whitePath = path.join(dir, 'white.json');
690
+ fs.writeFileSync(whitePath, JSON.stringify(whiteData, null, 2), 'utf8');
691
+
692
+ // 保存黑名单数据
693
+ const blackData = {
694
+ black: this.getAllBlack(),
695
+ black_time: Array.from(this._black_time.entries()),
696
+ timestamp: timestamp
697
+ };
698
+ const blackPath = path.join(dir, 'black.json');
699
+ fs.writeFileSync(blackPath, JSON.stringify(blackData, null, 2), 'utf8');
700
+
701
+ // 保存违规记录数据
702
+ const violationData = {
703
+ violation_count: Array.from(this._violation_count.entries()),
704
+ violation_time: Array.from(this._violation_time.entries()),
705
+ timestamp: timestamp
706
+ };
707
+ const violationPath = path.join(dir, 'violation.json');
708
+ fs.writeFileSync(violationPath, JSON.stringify(violationData, null, 2), 'utf8');
709
+
710
+ this.logger('info', 'IP数据已分文件保存:', {
711
+ white: whitePath,
712
+ black: blackPath,
713
+ violation: violationPath
714
+ });
715
+ return true;
716
+ } catch (err) {
717
+ this.logger('error', '保存IP数据失败:', err.message);
718
+ return false;
719
+ }
720
+ };
721
+
722
+ /**
723
+ * 从文件加载IP数据(持久化存储)
724
+ * @returns {boolean} 是否加载成功
725
+ */
726
+ Ip.prototype.load = function() {
727
+ try {
728
+ const fs = require('fs');
729
+ const path = require('path');
730
+
731
+ const dir = this._config.dir;
732
+ let loadedCount = 0;
733
+
734
+ // 加载白名单数据
735
+ const whitePath = path.join(dir, 'white.json');
736
+ if (fs.existsSync(whitePath)) {
737
+ const content = fs.readFileSync(whitePath, 'utf8');
738
+ const data = JSON.parse(content);
739
+
740
+ if (Array.isArray(data.white)) {
741
+ for (const ip of data.white) {
742
+ if (typeof ip === 'string') {
743
+ this._white.add(ip);
744
+ }
745
+ }
746
+ loadedCount++;
747
+ this.logger('info', '白名单数据已加载:', whitePath);
748
+ }
749
+ }
750
+
751
+ // 加载黑名单数据
752
+ const blackPath = path.join(dir, 'black.json');
753
+ if (fs.existsSync(blackPath)) {
754
+ const content = fs.readFileSync(blackPath, 'utf8');
755
+ const data = JSON.parse(content);
756
+
757
+ // 加载黑名单
758
+ if (Array.isArray(data.black)) {
759
+ for (const ip of data.black) {
760
+ if (typeof ip === 'string') {
761
+ this._black.add(ip);
762
+ }
763
+ }
764
+ }
765
+
766
+ // 加载黑名单过期时间
767
+ if (Array.isArray(data.black_time)) {
768
+ for (const [ip, time] of data.black_time) {
769
+ if (typeof ip === 'string' && typeof time === 'number') {
770
+ this._black_time.set(ip, time);
771
+ }
772
+ }
773
+ }
774
+
775
+ loadedCount++;
776
+ this.logger('info', '黑名单数据已加载:', blackPath);
777
+ }
778
+
779
+ // 加载违规记录数据
780
+ const violationPath = path.join(dir, 'violation.json');
781
+ if (fs.existsSync(violationPath)) {
782
+ const content = fs.readFileSync(violationPath, 'utf8');
783
+ const data = JSON.parse(content);
784
+
785
+ // 加载违规记录
786
+ if (Array.isArray(data.violation_count)) {
787
+ for (const [ip, count] of data.violation_count) {
788
+ if (typeof ip === 'string' && typeof count === 'number') {
789
+ this._violation_count.set(ip, count);
790
+ }
791
+ }
792
+ }
793
+
794
+ if (Array.isArray(data.violation_time)) {
795
+ for (const [ip, time] of data.violation_time) {
796
+ if (typeof ip === 'string' && typeof time === 'number') {
797
+ this._violation_time.set(ip, time);
798
+ }
799
+ }
800
+ }
801
+
802
+ loadedCount++;
803
+ this.logger('info', '违规记录数据已加载:', violationPath);
804
+ }
805
+
806
+ if (loadedCount === 0) {
807
+ this.logger('info', '未找到任何IP数据文件,跳过加载');
808
+ } else {
809
+ this.logger('info', 'IP数据加载完成,统计:', {
810
+ white_count: this.getAllWhite().length,
811
+ black_count: this.getAllBlack().length,
812
+ violation_count: this.getAllViolationIps().length,
813
+ files_loaded: loadedCount
814
+ });
815
+ }
816
+
817
+ return true;
818
+ } catch (err) {
819
+ this.logger('error', '加载IP数据失败:', err.message);
820
+ return false;
821
+ }
822
+ };
823
+
824
+ /**
825
+ * 自动保存数据(定时保存)
826
+ * @param {number} interval - 保存间隔(毫秒),默认5分钟
827
+ */
828
+ Ip.prototype.autoSave = function(interval = 300000) {
829
+ if (this._autoSaveTimer) {
830
+ clearInterval(this._autoSaveTimer);
831
+ }
832
+
833
+ this._autoSaveTimer = setInterval(() => {
834
+ this.save();
835
+ }, interval);
836
+
837
+ this.logger('info', '自动保存已启动,间隔:', interval, 'ms');
838
+ };
839
+
840
+ /**
841
+ * 停止自动保存
842
+ */
843
+ Ip.prototype.stopAutoSave = function() {
844
+ if (this._autoSaveTimer) {
845
+ clearInterval(this._autoSaveTimer);
846
+ this._autoSaveTimer = null;
847
+ this.logger('info', '自动保存已停止');
848
+ }
623
849
  };
624
850
 
625
851
  /**
@@ -669,9 +895,14 @@ Ip.prototype.del = function(ip) {
669
895
  result.black_time = true;
670
896
  }
671
897
 
672
- // 如果有任何删除操作,记录日志
898
+ // 如果有任何删除操作,记录日志并自动保存
673
899
  if (Object.values(result).some(Boolean)) {
674
900
  this.logger('info', '删除IP记录:', { ip, result });
901
+
902
+ // 自动保存到持久化存储
903
+ if (this._config.dir) {
904
+ this.save();
905
+ }
675
906
  }
676
907
 
677
908
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_ip",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "用于管理IP名单,可设置白名单、黑名单和IP检查,查询IP请求次数、频率等。",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -198,6 +198,135 @@ setTimeout(() => {
198
198
  ip_manager.clearViolations();
199
199
  console.log('清空后违规记录数量:', Object.keys(ip_manager.getAllViolations()).length);
200
200
 
201
+ // 测试13: 持久化存储功能(分文件存储)
202
+ console.log('\n13. 测试持久化存储功能(分文件存储):');
203
+
204
+ // 创建带持久化配置的实例
205
+ const persistent_ip = new Ip({
206
+ dir: './cache/ip',
207
+ max_white: 3,
208
+ max_black: 3
209
+ });
210
+ persistent_ip.setup(logger);
211
+
212
+ // 添加测试数据
213
+ console.log('添加测试数据到持久化实例:');
214
+ persistent_ip.addWhite('192.168.300.1');
215
+ persistent_ip.addWhite('192.168.300.2');
216
+ persistent_ip.addBlack('10.0.300.1');
217
+ persistent_ip.addBlack('10.0.300.2');
218
+ persistent_ip.recordViolation('172.16.300.1', '测试违规');
219
+
220
+ console.log('保存前数据统计:');
221
+ console.log('白名单数量:', persistent_ip.getAllWhite().length);
222
+ console.log('黑名单数量:', persistent_ip.getAllBlack().length);
223
+ console.log('违规记录数量:', persistent_ip.getAllViolationIps().length);
224
+
225
+ // 保存数据到分文件
226
+ console.log('保存数据到分文件:', persistent_ip.save());
227
+
228
+ // 验证文件是否创建
229
+ const fs = require('fs');
230
+ const path = require('path');
231
+ const whiteFile = path.join('./cache/ip', 'white.json');
232
+ const blackFile = path.join('./cache/ip', 'black.json');
233
+ const violationFile = path.join('./cache/ip', 'violation.json');
234
+
235
+ console.log('检查分文件存储:');
236
+ console.log('白名单文件存在:', fs.existsSync(whiteFile));
237
+ console.log('黑名单文件存在:', fs.existsSync(blackFile));
238
+ console.log('违规记录文件存在:', fs.existsSync(violationFile));
239
+
240
+ // 验证文件内容
241
+ if (fs.existsSync(whiteFile)) {
242
+ const whiteData = JSON.parse(fs.readFileSync(whiteFile, 'utf8'));
243
+ console.log('白名单文件数据:', whiteData.white);
244
+ }
245
+
246
+ if (fs.existsSync(blackFile)) {
247
+ const blackData = JSON.parse(fs.readFileSync(blackFile, 'utf8'));
248
+ console.log('黑名单文件数据:', blackData.black);
249
+ }
250
+
251
+ if (fs.existsSync(violationFile)) {
252
+ const violationData = JSON.parse(fs.readFileSync(violationFile, 'utf8'));
253
+ console.log('违规记录文件数据:', violationData.violation_count);
254
+ }
255
+
256
+ // 创建新实例并加载数据
257
+ console.log('创建新实例并加载数据:');
258
+ const loaded_ip = new Ip({
259
+ dir: './cache/ip'
260
+ });
261
+ loaded_ip.setup(logger);
262
+
263
+ console.log('加载后数据统计:');
264
+ console.log('白名单数量:', loaded_ip.getAllWhite().length);
265
+ console.log('黑名单数量:', loaded_ip.getAllBlack().length);
266
+ console.log('违规记录数量:', loaded_ip.getAllViolationIps().length);
267
+
268
+ // 验证数据一致性
269
+ console.log('验证数据一致性:');
270
+ console.log('192.168.300.1 在白名单:', loaded_ip.isWhite('192.168.300.1'));
271
+ console.log('10.0.300.1 在黑名单:', loaded_ip.isBlack('10.0.300.1'));
272
+ console.log('172.16.300.1 违规次数:', loaded_ip.getViolationCount('172.16.300.1'));
273
+
274
+ // 测试自动保存
275
+ console.log('\n测试自动保存功能:');
276
+ loaded_ip.autoSave(2000); // 2秒间隔便于测试
277
+
278
+ // 添加新数据
279
+ setTimeout(() => {
280
+ console.log('添加新数据触发自动保存:');
281
+ loaded_ip.addWhite('192.168.300.3');
282
+
283
+ // 停止自动保存
284
+ setTimeout(() => {
285
+ loaded_ip.stopAutoSave();
286
+ console.log('自动保存已停止');
287
+
288
+ // 测试删除操作触发自动保存
289
+ console.log('测试删除操作触发自动保存:');
290
+ loaded_ip.del('192.168.300.1');
291
+
292
+ // 测试清空操作触发自动保存
293
+ console.log('测试清空操作触发自动保存:');
294
+ loaded_ip.clearWhite();
295
+
296
+ console.log('持久化存储功能测试完成');
297
+
298
+ // 测试14: 删除IP记录功能
299
+ console.log('\n14. 测试删除IP记录功能:');
300
+
301
+ // 准备测试数据
302
+ ip_manager.addBlack('192.168.300.1');
303
+ ip_manager.addWhite('192.168.300.1');
304
+ ip_manager.recordViolation('192.168.300.1', '测试违规');
305
+
306
+ console.log('删除前状态:');
307
+ console.log('192.168.300.1 在黑名单:', ip_manager.isBlack('192.168.300.1'));
308
+ console.log('192.168.300.1 在白名单:', ip_manager.isWhite('192.168.300.1'));
309
+ console.log('192.168.300.1 违规次数:', ip_manager.getViolationCount('192.168.300.1'));
310
+ console.log('192.168.300.1 黑名单过期时间:', ip_manager.getBlackExpireTime('192.168.300.1'));
311
+
312
+ // 删除IP记录
313
+ const delete_result = ip_manager.del('192.168.300.1');
314
+ console.log('删除结果:', delete_result);
315
+
316
+ console.log('删除后状态:');
317
+ console.log('192.168.300.1 在黑名单:', ip_manager.isBlack('192.168.300.1'));
318
+ console.log('192.168.300.1 在白名单:', ip_manager.isWhite('192.168.300.1'));
319
+ console.log('192.168.300.1 违规次数:', ip_manager.getViolationCount('192.168.300.1'));
320
+ console.log('192.168.300.1 黑名单过期时间:', ip_manager.getBlackExpireTime('192.168.300.1'));
321
+
322
+ // 测试删除不存在的IP
323
+ const delete_none_result = ip_manager.del('192.168.999.999');
324
+ console.log('删除不存在IP的结果:', delete_none_result);
325
+
326
+ console.log('\n=== IP管理模块测试结束 ===');
327
+ }, 3000);
328
+ }, 1000);
329
+
201
330
  // 测试违规记录过期清理
202
331
  console.log('\n测试违规记录过期清理:');
203
332
  console.log('等待12秒后检查违规记录过期清理...');