mm_os 2.1.8 → 2.2.0
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/core/com/event/index.js +1 -0
- package/core/com/eventer/com.js +41 -17
- package/core/com/mqtt/config.tpl.json +34 -10
- package/core/com/mqtt/drive.js +420 -48
- package/core/com/mqtt/index.js +321 -39
- package/core/com/mqtt/mm_mqtt.js +327 -0
- package/core/com/mqtt/script.js +9 -8
- package/core/com/plugin/config.tpl.json +6 -0
- package/core/com/plugin/drive.js +12 -8
- package/demo/app/test/event_api/client/event.json +3 -1
- package/demo/app/test/event_api/client/main.js +1 -0
- package/demo/app/test/mqtt/df/index.js +364 -0
- package/demo/app/test/mqtt/df/mqtt.json +34 -0
- package/demo/app/test/mqtt/test/index.js +38 -0
- package/demo/app/test/mqtt/test/mqtt.json +24 -0
- package/demo/app/test/mqtt/zs/index.js +430 -0
- package/demo/app/test/mqtt/zs/mqtt.json +34 -0
- package/demo/com/server/com.json +4 -0
- package/demo/com/server/index.js +447 -0
- package/demo/config/development.json +10 -4
- package/demo/config/local.json +4 -4
- package/demo/config/test.json +1 -1
- package/demo/index.js +9 -0
- package/index.js +0 -1
- package/middleware/waf_ip/index.js +106 -0
- package/middleware/waf_ip/middleware.json +10 -0
- package/middleware/web_event/index.js +5 -3
- package/package.json +3 -3
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
var sql = $.mysql_admin('sys');
|
|
2
|
+
var dbs = sql.dbs;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 服务端类
|
|
6
|
+
*/
|
|
7
|
+
class Server {
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 获取用户
|
|
13
|
+
* @param {String} table 数据表
|
|
14
|
+
* @param {Number} project_id 项目ID
|
|
15
|
+
* @param {String} customId 自定义身份ID
|
|
16
|
+
* @param {String} name 用户姓名
|
|
17
|
+
* @param {String} phone 用户手机号码
|
|
18
|
+
* @param {String} idcard 用户身份证号
|
|
19
|
+
* @returns {Object} 返回用户对象
|
|
20
|
+
*/
|
|
21
|
+
Server.prototype.get_user_sub = async function(table, project_id, customId, name, phone, idcard) {
|
|
22
|
+
var db1 = dbs.new("face_" + table, "user_id");
|
|
23
|
+
var query = {
|
|
24
|
+
project_id
|
|
25
|
+
}
|
|
26
|
+
if (customId && customId !== "0") {
|
|
27
|
+
query.customId = customId;
|
|
28
|
+
} else {
|
|
29
|
+
query.name = name;
|
|
30
|
+
if (phone) {
|
|
31
|
+
query.phone = phone;
|
|
32
|
+
} else if (idcard) {
|
|
33
|
+
query.idcard = idcard;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// 先查询1次,看内部人员是否存在
|
|
37
|
+
var enter = await db2.getObj(query, "", "*", false);
|
|
38
|
+
|
|
39
|
+
if (!enter) {
|
|
40
|
+
// 如果不存在,则用名字再查一次,看内部人员是否存在
|
|
41
|
+
query = {
|
|
42
|
+
project_id,
|
|
43
|
+
name
|
|
44
|
+
};
|
|
45
|
+
enter = await db2.getObj(query, "`time_create` desc", "*", false);
|
|
46
|
+
}
|
|
47
|
+
return enter;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 获取用户
|
|
52
|
+
* @param {String} project_id 项目ID
|
|
53
|
+
* @param {String} table 数据表
|
|
54
|
+
* @param {Number} project_id 项目ID
|
|
55
|
+
* @param {String} customId 自定义身份ID
|
|
56
|
+
* @param {String} name 用户姓名
|
|
57
|
+
* @param {String} phone 用户手机号码
|
|
58
|
+
* @param {String} idcard 用户身份证号
|
|
59
|
+
* @returns {Object} 返回用户对象和用户类型
|
|
60
|
+
*/
|
|
61
|
+
Server.prototype.get_user = async function(project_id, customId, name, phone, idcard) {
|
|
62
|
+
// 默认为 1内部人员类型
|
|
63
|
+
var user_type = 1;
|
|
64
|
+
var enter = await this.get_user_sub("enter", project_id, customId, name, phone, idcard);
|
|
65
|
+
|
|
66
|
+
if (!enter) {
|
|
67
|
+
// 2为访客
|
|
68
|
+
user_type = 2;
|
|
69
|
+
enter = await this.get_user_sub("visitor", project_id, customId, name, phone, idcard);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (enter) {
|
|
73
|
+
var by = {};
|
|
74
|
+
if (!enter.customId && customId && customId !== "0") {
|
|
75
|
+
by.customId = customId;
|
|
76
|
+
}
|
|
77
|
+
if (!enter.phone && phone) {
|
|
78
|
+
by.phone = phone;
|
|
79
|
+
}
|
|
80
|
+
if (!enter.idcard && idcard && idcard !== '0') {
|
|
81
|
+
by.idcard = idcard;
|
|
82
|
+
}
|
|
83
|
+
if (Object.keys(by).length) {
|
|
84
|
+
var db3;
|
|
85
|
+
var qy = {};
|
|
86
|
+
if (user_type == 2) {
|
|
87
|
+
db3 = dbs.new("face_visitor", "visitor_id");
|
|
88
|
+
qy.visitor_id = enter.visitor_id
|
|
89
|
+
} else {
|
|
90
|
+
db3 = dbs.new("face_enter", "user_id");
|
|
91
|
+
qy.user_id == enter.user_id;
|
|
92
|
+
qy.project_id = enter.project_id;
|
|
93
|
+
}
|
|
94
|
+
await db3.set(qy, by);
|
|
95
|
+
enter = Object.assign({}, enter, by);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
// 3为外部人员(非平台成员)
|
|
99
|
+
user_type = 3;
|
|
100
|
+
enter = {
|
|
101
|
+
department_id: 0,
|
|
102
|
+
team_id: 0,
|
|
103
|
+
job: '',
|
|
104
|
+
phone,
|
|
105
|
+
idcard
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
var user = Object.assign({}, enter, {
|
|
109
|
+
customId,
|
|
110
|
+
name,
|
|
111
|
+
phone,
|
|
112
|
+
idcard
|
|
113
|
+
})
|
|
114
|
+
return {
|
|
115
|
+
user_type,
|
|
116
|
+
user
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 处理上传记录
|
|
122
|
+
* @param {String} clientid 设备ID
|
|
123
|
+
* @param {Object} log 记录
|
|
124
|
+
*/
|
|
125
|
+
Server.prototype.exec_log = async function(clientid, log) {
|
|
126
|
+
var {
|
|
127
|
+
device,
|
|
128
|
+
tip
|
|
129
|
+
} = await this.check_device(clientid);
|
|
130
|
+
|
|
131
|
+
if (tip) {
|
|
132
|
+
return tip
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var project_id = device.project_id;
|
|
136
|
+
var {
|
|
137
|
+
project,
|
|
138
|
+
tip
|
|
139
|
+
} = check_project(project_id);
|
|
140
|
+
|
|
141
|
+
if (tip) {
|
|
142
|
+
return tip
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
var {
|
|
146
|
+
customId,
|
|
147
|
+
name,
|
|
148
|
+
phone,
|
|
149
|
+
idcard
|
|
150
|
+
} = log;
|
|
151
|
+
// 通过项目id和用户唯一标识获取用户
|
|
152
|
+
var {
|
|
153
|
+
user,
|
|
154
|
+
user_type
|
|
155
|
+
} = await this.get_user(project_id, customId, name, phone, idcard);
|
|
156
|
+
|
|
157
|
+
// 如果不记录外部人员,则终止,不保存记录
|
|
158
|
+
if (!project.save_outboard && user_type === 3) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
log.user_type = user_type;
|
|
162
|
+
log.clientid = clientid;
|
|
163
|
+
log.direction = device.direction;
|
|
164
|
+
return this.save_log(log);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 检查设备
|
|
169
|
+
* @param {String} clientid 客户端ID
|
|
170
|
+
* @param {Object} key 键
|
|
171
|
+
*/
|
|
172
|
+
Server.prototype.check_device = async function(clientid, key) {
|
|
173
|
+
var tip;
|
|
174
|
+
var db2 = dbs.new("face_device");
|
|
175
|
+
var device = await db2.getObj({
|
|
176
|
+
clientid
|
|
177
|
+
});
|
|
178
|
+
if (device) {
|
|
179
|
+
if (device.available) {
|
|
180
|
+
if (key && !device[key]) {
|
|
181
|
+
tip = "没有功能权限"
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
tip = "设备已禁用"
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
tip = "没有找到设备"
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
device,
|
|
191
|
+
tip
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 检查项目
|
|
198
|
+
* @param {String} project_id 项目ID
|
|
199
|
+
* @param {Object} key 键
|
|
200
|
+
*/
|
|
201
|
+
Server.prototype.check_project = async function(project_id, key) {
|
|
202
|
+
var tip;
|
|
203
|
+
var db2 = dbs.new("face_project");
|
|
204
|
+
var project = await db2.getObj({
|
|
205
|
+
project_id
|
|
206
|
+
});
|
|
207
|
+
if (project) {
|
|
208
|
+
if (project.available) {
|
|
209
|
+
var now = new Date().getTime();
|
|
210
|
+
if (now > new Date(project.time_valid).getTime()) {
|
|
211
|
+
tip = "项目已过期"
|
|
212
|
+
} else if (key && !project[key]) {
|
|
213
|
+
tip = "没有功能权限"
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
tip = "项目已禁用"
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
tip = "没有找到项目"
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
project,
|
|
223
|
+
tip
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 保存记录
|
|
229
|
+
* @param {Object} log 记录
|
|
230
|
+
*/
|
|
231
|
+
Server.prototype.save_log = async function(log) {
|
|
232
|
+
var db = dbs.new("face_log", "user_id");
|
|
233
|
+
var project_id = log.project_id;
|
|
234
|
+
var user_id = log.user_id || 0;
|
|
235
|
+
var time = log.time;
|
|
236
|
+
var count = await db.count({
|
|
237
|
+
project_id,
|
|
238
|
+
user_id,
|
|
239
|
+
time
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// 如果记录已存在,则不再保存
|
|
243
|
+
if (count) {
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 重新定义方向
|
|
248
|
+
var direction = log.direction;
|
|
249
|
+
if (user_id && direction == "通用") {
|
|
250
|
+
var qy = {
|
|
251
|
+
user_id,
|
|
252
|
+
project_id,
|
|
253
|
+
type_has: "1,3,4",
|
|
254
|
+
time_min: now.toStr('yyyy-MM-dd 00:00:00')
|
|
255
|
+
};
|
|
256
|
+
var obj = await db.getObj(qy, '`time` desc');
|
|
257
|
+
if (obj) {
|
|
258
|
+
direction = obj.direction == "进" ? "出" : "进"
|
|
259
|
+
} else {
|
|
260
|
+
direction = "进"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
log.direction = direction;
|
|
264
|
+
|
|
265
|
+
// 重新定义头像
|
|
266
|
+
var pic;
|
|
267
|
+
var fname = time.replace(/[-: ]/g, '_');
|
|
268
|
+
var avatar = log.avatar;
|
|
269
|
+
if (avatar) {
|
|
270
|
+
if (project.upload_pic) {
|
|
271
|
+
pic = avatar;
|
|
272
|
+
avatar = `/face/img/user/${user_id}/${fname}.png`;
|
|
273
|
+
} else {
|
|
274
|
+
avatar = "";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 如果是访客则追加备注
|
|
279
|
+
var visitor_id = log.visitor_id;
|
|
280
|
+
if (visitor_id) {
|
|
281
|
+
var {
|
|
282
|
+
respondent,
|
|
283
|
+
date,
|
|
284
|
+
source
|
|
285
|
+
} = log;
|
|
286
|
+
if (typeof(date) == "string") {
|
|
287
|
+
date = date.toTime().toStr("yyyy-MM-dd");
|
|
288
|
+
} else if (typeof(date) == "object") {
|
|
289
|
+
date = date.toStr("yyyy-MM-dd");
|
|
290
|
+
} else {
|
|
291
|
+
date = ''
|
|
292
|
+
}
|
|
293
|
+
log.note = `${visitor_id},${source},${date},${respondent},${log.nfc}`;
|
|
294
|
+
delete log.visitor_id;
|
|
295
|
+
delete log.respondent;
|
|
296
|
+
delete log.date;
|
|
297
|
+
delete log.source;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// 添加新记录
|
|
301
|
+
var n = await db.add(log);
|
|
302
|
+
|
|
303
|
+
var bl = n > 0;
|
|
304
|
+
if (bl) {
|
|
305
|
+
// 更新用户状态
|
|
306
|
+
var body = {
|
|
307
|
+
clientid: log.clientid,
|
|
308
|
+
direction,
|
|
309
|
+
time
|
|
310
|
+
};
|
|
311
|
+
if (log.user_type == 1) {
|
|
312
|
+
var db4 = dbs.new("face_enter", "enter_id");
|
|
313
|
+
await db4.set({
|
|
314
|
+
user_id,
|
|
315
|
+
project_id
|
|
316
|
+
}, body);
|
|
317
|
+
} else if (user_type == 2) {
|
|
318
|
+
var db4 = dbs.new("face_visitor", "visitor_id");
|
|
319
|
+
await db4.set({
|
|
320
|
+
visitor_id
|
|
321
|
+
}, body);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (pic) {
|
|
325
|
+
var file = (`/app/face/static/img/user/${user_id}/${fname}.png`).fullname();
|
|
326
|
+
file.addDir();
|
|
327
|
+
var po = pic.replace(/^data:image\/\w+;base64,/, "");
|
|
328
|
+
var bf = Buffer.from(po, 'base64');
|
|
329
|
+
fs.writeFileSync(file, bf);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return bl;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* 处理扫描二维码开门
|
|
337
|
+
* @param {String} clientid 客户端ID
|
|
338
|
+
* @param {String} qrcode 二维码内容
|
|
339
|
+
*/
|
|
340
|
+
Server.prototype.exec_qrcode = async function(clientid, qrcode = "") {
|
|
341
|
+
var ret;
|
|
342
|
+
var db = dbs.new("face_qrcode", "qrcode_id");
|
|
343
|
+
var now = new Date();
|
|
344
|
+
var time = now.toStr('yyyy-MM-dd hh:mm:ss');
|
|
345
|
+
var obj = await db.getObj({
|
|
346
|
+
qrcode,
|
|
347
|
+
time_end_min: time
|
|
348
|
+
});
|
|
349
|
+
if (obj) {
|
|
350
|
+
var {
|
|
351
|
+
device,
|
|
352
|
+
tip
|
|
353
|
+
} = await this.check_device(clientid, "qrcode");
|
|
354
|
+
if (tip) {
|
|
355
|
+
// 发送开门控制
|
|
356
|
+
ret = {
|
|
357
|
+
"uuid": obj.user_id,
|
|
358
|
+
// 0不开门,1开门
|
|
359
|
+
"pass": false,
|
|
360
|
+
"tip": tip
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
if (obj.count == 0 || obj.num < obj.count) {
|
|
364
|
+
var db = dbs.new("face_enter");
|
|
365
|
+
var user = await db.getObj({
|
|
366
|
+
user_id: obj.user_id,
|
|
367
|
+
project_id: obj.project_id,
|
|
368
|
+
state: 3
|
|
369
|
+
});
|
|
370
|
+
if (user) {
|
|
371
|
+
if (user.client && user.client.indexOf(clientid) !== -1) {
|
|
372
|
+
obj.num++;
|
|
373
|
+
// 发送开门控制
|
|
374
|
+
ret = {
|
|
375
|
+
"uuid": user.customId || user.project_id + "-" + user.user_id,
|
|
376
|
+
// 0不开门,1开门
|
|
377
|
+
"pass": true,
|
|
378
|
+
"tip": "请通行",
|
|
379
|
+
user
|
|
380
|
+
}
|
|
381
|
+
var log = {
|
|
382
|
+
project_id: 0,
|
|
383
|
+
user_id: 0,
|
|
384
|
+
name: "",
|
|
385
|
+
// 1内部人员|2访客|3非系统名单
|
|
386
|
+
user_type: 1,
|
|
387
|
+
// 1人脸验证|2远程开门|3扫码开门|4刷卡验证
|
|
388
|
+
type: 3,
|
|
389
|
+
record_type: 1,
|
|
390
|
+
action: "智码开门",
|
|
391
|
+
// 1白名单|2黑名单
|
|
392
|
+
person_type: 1,
|
|
393
|
+
department_id: 0,
|
|
394
|
+
team_id: 0,
|
|
395
|
+
job: "",
|
|
396
|
+
phone: "",
|
|
397
|
+
idcard: "",
|
|
398
|
+
nfc: "",
|
|
399
|
+
note: ""
|
|
400
|
+
}
|
|
401
|
+
$.push(u, user);
|
|
402
|
+
log.direction = device.direction;
|
|
403
|
+
log.clientid = clientid;
|
|
404
|
+
log.time = time;
|
|
405
|
+
await this.save_log(log);
|
|
406
|
+
} else {
|
|
407
|
+
// 发送开门控制
|
|
408
|
+
ret = {
|
|
409
|
+
"uuid": user.customId || user.project_id + "-" + user.user_id,
|
|
410
|
+
// 0不开门,1开门
|
|
411
|
+
"pass": false,
|
|
412
|
+
"tip": "没有访问权限"
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
// 发送开门控制
|
|
417
|
+
ret = {
|
|
418
|
+
"uuid": obj.project_id + "-" + obj.user_id,
|
|
419
|
+
// 0不开门,1开门
|
|
420
|
+
"pass": false,
|
|
421
|
+
"tip": "非法用户"
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
} else {
|
|
425
|
+
// 发送开门控制
|
|
426
|
+
ret = {
|
|
427
|
+
"uuid": obj.project_id + "-" + obj.user_id,
|
|
428
|
+
// 0不开门,1开门
|
|
429
|
+
"pass": false,
|
|
430
|
+
"tip": "使用次数超限"
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
// 发送开门控制
|
|
436
|
+
ret = {
|
|
437
|
+
"uuid": "0",
|
|
438
|
+
// 0不开门,1开门
|
|
439
|
+
"pass": false,
|
|
440
|
+
"tip": "非法二维码"
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return ret;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
$.server = new Server();
|
|
@@ -34,16 +34,22 @@
|
|
|
34
34
|
// 静态文件缓存时长
|
|
35
35
|
"max_age": 120000,
|
|
36
36
|
// 代理转发
|
|
37
|
-
"proxy": {}
|
|
37
|
+
"proxy": {},
|
|
38
|
+
// 单位秒, 3600 = 1小时
|
|
39
|
+
"request_duration": 60,
|
|
40
|
+
// 请求次数上限
|
|
41
|
+
"request_limit": 10,
|
|
42
|
+
// 是否加入黑名单
|
|
43
|
+
"request_block": true
|
|
38
44
|
},
|
|
39
45
|
"mqtt": {
|
|
40
46
|
// 是否启用MQTT
|
|
41
|
-
"state":
|
|
47
|
+
"state": true,
|
|
42
48
|
// mqtt访问端口号
|
|
43
49
|
"socket_port": 1883,
|
|
44
50
|
// websocket 访问端口
|
|
45
51
|
"http_port": 8083,
|
|
46
|
-
// 缓存方式
|
|
52
|
+
// 缓存方式 memory、mongodb、redis
|
|
47
53
|
"cache": "memory",
|
|
48
54
|
// 缓存服务器地址
|
|
49
55
|
"cache_host": "mongodb://localhost:27017/mosca",
|
|
@@ -52,7 +58,7 @@
|
|
|
52
58
|
// 协议头
|
|
53
59
|
"protocol": "mqtt",
|
|
54
60
|
// MQTT服务器地址
|
|
55
|
-
"hostname": "
|
|
61
|
+
"hostname": "127.0.0.1",
|
|
56
62
|
// MQTT服务器用户名
|
|
57
63
|
"username": "developer",
|
|
58
64
|
// MQTT服务器密码
|
package/demo/config/local.json
CHANGED
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"proxy": {}
|
|
38
38
|
},
|
|
39
39
|
"mqtt": {
|
|
40
|
-
"state":
|
|
40
|
+
"state": true,
|
|
41
41
|
// mqtt访问端口号
|
|
42
42
|
"socket_port": 1883,
|
|
43
43
|
// 服务端
|
|
44
44
|
"http_host": "localhost",
|
|
45
45
|
// websocket 访问端口
|
|
46
46
|
"http_port": 8083,
|
|
47
|
-
// 缓存方式
|
|
48
|
-
"cache": "
|
|
47
|
+
// 缓存方式 memory、mongodb、redis
|
|
48
|
+
"cache": "memory",
|
|
49
49
|
// 缓存服务器地址
|
|
50
50
|
"cache_host": "mongodb://localhost:27017/mosca",
|
|
51
51
|
// MQTT订阅方式
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
// MQTT服务器用户名
|
|
58
58
|
"username": "server",
|
|
59
59
|
// MQTT服务器密码
|
|
60
|
-
"password": "
|
|
60
|
+
"password": "asd123",
|
|
61
61
|
"port": 1883
|
|
62
62
|
},
|
|
63
63
|
"mysql": {
|
package/demo/config/test.json
CHANGED
package/demo/index.js
CHANGED
|
@@ -11,4 +11,13 @@ $.sql = $.mysql_admin('sys', __dirname);
|
|
|
11
11
|
$.sql.setConfig(config.mysql);
|
|
12
12
|
$.sql.open();
|
|
13
13
|
|
|
14
|
+
setTimeout(async () => {
|
|
15
|
+
var mqtt = $.mqtt_admin("sys");
|
|
16
|
+
mqtt.init(config.mqtt);
|
|
17
|
+
mqtt.start();
|
|
18
|
+
await mqtt.update();
|
|
19
|
+
mqtt.run(null, 'init');
|
|
20
|
+
// console.log("打印", $.eventer, mqtt);
|
|
21
|
+
}, 2000);
|
|
22
|
+
|
|
14
23
|
os.run();
|
package/index.js
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const {
|
|
3
|
+
exec
|
|
4
|
+
} = require('child_process');
|
|
5
|
+
const platform = os.platform();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 获取客户端IP
|
|
9
|
+
* @param {Object} req 请求对象
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
function getClientIP(req) {
|
|
13
|
+
return req.headers['x-forwarded-for'] || req.headers['X-Forwarded-For'] ||
|
|
14
|
+
req.connection.remoteAddress ||
|
|
15
|
+
req.socket.remoteAddress ||
|
|
16
|
+
req.connection.socket.remoteAddress;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 设置黑名单
|
|
21
|
+
* @param {String} ip IP地址
|
|
22
|
+
*/
|
|
23
|
+
function setting_blacklist(ip) {
|
|
24
|
+
var cmd;
|
|
25
|
+
if (platform == "win32") {
|
|
26
|
+
// window 系统
|
|
27
|
+
cmd =
|
|
28
|
+
`netsh advfirewall firewall add rule name="Blacklist ${ip}" dir=in action=block remoteip="${ip}" protocol=any`
|
|
29
|
+
} else {
|
|
30
|
+
// linux 系统
|
|
31
|
+
cmd = `sudo iptables -A INPUT -s ${ip} -j DROP`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exec(cmd, (error, stdout, stderr) => {
|
|
35
|
+
if (error) {
|
|
36
|
+
console.error(`执行的错误: ${error}`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
$.log.info(`加入黑名单: ${ip}`);
|
|
40
|
+
if (stderr) {
|
|
41
|
+
console.error(`标准错误输出: ${stderr}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 应用
|
|
48
|
+
* @param {Object} server 服务
|
|
49
|
+
* @param {Object} config 配置参数
|
|
50
|
+
*/
|
|
51
|
+
module.exports = function(server, config) {
|
|
52
|
+
var limit = config.request_limit || 0;
|
|
53
|
+
var duration = config.request_duration || 0;
|
|
54
|
+
var block = config.request_block || false;
|
|
55
|
+
|
|
56
|
+
if (limit && duration) {
|
|
57
|
+
/* WAF(web防火墙) */
|
|
58
|
+
server.use(async (ctx, next) => {
|
|
59
|
+
var pass = true;
|
|
60
|
+
// 获取IP
|
|
61
|
+
var ip = getClientIP(ctx.req);
|
|
62
|
+
var num = 1;
|
|
63
|
+
var now = new Date();
|
|
64
|
+
var date = now.toStr('yyyy-MM-dd');
|
|
65
|
+
var time;
|
|
66
|
+
var str = await $.cache.get("ip_" + ip);
|
|
67
|
+
var json;
|
|
68
|
+
if (str) {
|
|
69
|
+
json = JSON.parse(str);
|
|
70
|
+
if (json.date !== date) {
|
|
71
|
+
num = 1;
|
|
72
|
+
} else {
|
|
73
|
+
// 判断时间间隔是否在范围外
|
|
74
|
+
if (json.time.toTime().interval(now) > duration) {
|
|
75
|
+
num = 1;
|
|
76
|
+
} else {
|
|
77
|
+
// 如果是在周期内,访问次数+1,并判断是否超出上限
|
|
78
|
+
num = json.num + 1;
|
|
79
|
+
if (num > limit) {
|
|
80
|
+
// 超出上限禁止访问,并加入黑名单
|
|
81
|
+
pass = false;
|
|
82
|
+
if (block) {
|
|
83
|
+
setting_blacklist(ip);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!time) {
|
|
90
|
+
time = now.toStr('yyyy-MM-dd hh:mm:ss');
|
|
91
|
+
}
|
|
92
|
+
if (pass) {
|
|
93
|
+
await $.cache.set("ip_" + ip, JSON.stringify({
|
|
94
|
+
date,
|
|
95
|
+
time,
|
|
96
|
+
num
|
|
97
|
+
}), duration);
|
|
98
|
+
await next();
|
|
99
|
+
} else {
|
|
100
|
+
ctx.status = 429;
|
|
101
|
+
ctx.body = '请求频率过高,请稍后再试。';
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return server;
|
|
106
|
+
};
|
|
@@ -48,10 +48,12 @@ class Event {
|
|
|
48
48
|
if (config.event && $.event_admin) {
|
|
49
49
|
// 创建一个API事件
|
|
50
50
|
var apis = $.event_admin('api', 'API事件');
|
|
51
|
-
apis.
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
apis.update_after = () => {
|
|
52
|
+
for (var k in this.events) {
|
|
53
|
+
this.events[k] = apis["list_" + k];
|
|
54
|
+
}
|
|
54
55
|
}
|
|
56
|
+
apis.update();
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
/**
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_os",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "这是超级美眉服务端框架,用于快速构建应用程序。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "cross-env NODE_ENV=test node ./demo/index.js",
|
|
8
|
-
"start": "node ./demo/index.js",
|
|
8
|
+
"start": "node --trace-warnings ./demo/index.js",
|
|
9
9
|
"dev": "cross-env NODE_ENV=development nodemon ./demo/index.js"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"mm_html": "^1.1.6",
|
|
42
42
|
"mm_koa_proxy": "^1.0.0",
|
|
43
43
|
"mm_logs": "^1.1.4",
|
|
44
|
-
"mm_machine": "^1.
|
|
44
|
+
"mm_machine": "^1.7.2",
|
|
45
45
|
"mm_mongodb": "^1.4.2",
|
|
46
46
|
"mm_mqtt": "^1.0.6",
|
|
47
47
|
"mm_mysql": "^1.8.0",
|