mm_os 3.2.8 → 3.3.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/README.md +47 -1
- package/core/base/mqtt/index.js +344 -157
- package/core/base/web/index.js +98 -11
- package/core/com/middleware/com.js +152 -152
- package/core/com/socket/config.tpl.json +2 -2
- package/core/com/socket/drive.js +2 -2
- package/core/com/socket/index.js +1 -1
- package/core/com/sql/drive.js +7 -7
- package/index.js +41 -37
- package/middleware/performance/index.js +150 -142
- package/middleware/security_audit/index.js +549 -0
- package/middleware/security_audit/middleware.json +48 -0
- package/middleware/security_headers/index.js +487 -0
- package/middleware/security_headers/middleware.json +45 -0
- package/middleware/waf/index.js +277 -6
- package/middleware/waf/middleware.json +2 -1
- package/middleware/waf_ddos/index.js +520 -0
- package/middleware/waf_ddos/middleware.json +38 -0
- package/middleware/waf_ip/index.js +231 -20
- package/middleware/waf_ip/middleware.json +43 -4
- package/middleware/waf_xss/index.js +269 -0
- package/middleware/waf_xss/middleware.json +18 -0
- package/middleware/web_before/middleware.json +1 -1
- package/middleware/web_socket/middleware.json +2 -2
- package/package.json +18 -7
- package/middleware/cors/index.js +0 -103
- package/middleware/cors/middleware.json +0 -9
- package/middleware/log/index.js +0 -32
- package/middleware/log/middleware.json +0 -9
- package/middleware/rate_limit/index.js +0 -112
- package/middleware/rate_limit/middleware.json +0 -10
- package/nodemon.json +0 -31
- package/package.txt +0 -1
- package/rps.bat +0 -3
- package/test.js +0 -5
- package/tps.bat +0 -3
- package/update.bat +0 -1
- package//347/263/273/347/273/237/346/236/266/346/236/204/350/257/204/344/274/260/344/270/216/344/274/230/345/214/226/345/273/272/350/256/256.md +0 -599
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_os",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "这是超级美眉服务端框架,用于快速构建应用程序。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "cross-env NODE_ENV=test node ./demo/index.js",
|
|
8
|
-
"start": "node --trace-warnings ./demo/index.js",
|
|
9
|
-
"dev": "cross-env NODE_ENV=development nodemon ./demo/index.js"
|
|
7
|
+
"test": "cross-env NODE_ENV=test node --no-warnings=DEP0060 ./demo/index.js",
|
|
8
|
+
"start": "node --trace-warnings --no-warnings=DEP0060 ./demo/index.js",
|
|
9
|
+
"dev": "cross-env NODE_ENV=development nodemon --no-warnings=DEP0060 ./demo/index.js"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
@@ -29,14 +29,25 @@
|
|
|
29
29
|
],
|
|
30
30
|
"author": "邱文武",
|
|
31
31
|
"license": "ISC",
|
|
32
|
+
"files": [
|
|
33
|
+
"index.js",
|
|
34
|
+
"core/**",
|
|
35
|
+
"lib/**",
|
|
36
|
+
"middleware/**",
|
|
37
|
+
"conf.json",
|
|
38
|
+
"README.md",
|
|
39
|
+
"README.en.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
32
42
|
"dependencies": {
|
|
33
|
-
"compressing": "^
|
|
34
|
-
"koa": "^3.0.
|
|
43
|
+
"compressing": "^2.0.0",
|
|
44
|
+
"koa": "^3.0.1",
|
|
35
45
|
"koa-body": "^6.0.1",
|
|
36
46
|
"koa-compress": "^5.1.1",
|
|
37
47
|
"koa-send": "^5.0.1",
|
|
38
48
|
"koa-websocket": "^7.0.0",
|
|
39
49
|
"mm_check": "^1.5.0",
|
|
50
|
+
"mm_email": "^1.0.3",
|
|
40
51
|
"mm_excel": "^1.2.2",
|
|
41
52
|
"mm_expand": "^1.8.3",
|
|
42
53
|
"mm_html": "^1.1.7",
|
|
@@ -53,6 +64,6 @@
|
|
|
53
64
|
"mm_tpl": "^2.4.3",
|
|
54
65
|
"mm_xml": "^1.1.7",
|
|
55
66
|
"mosca": "^2.8.3",
|
|
56
|
-
"mqtt": "^5.
|
|
67
|
+
"mqtt": "^5.14.1"
|
|
57
68
|
}
|
|
58
69
|
}
|
package/middleware/cors/index.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 跨域请求
|
|
3
|
-
* @param {Object} server 服务
|
|
4
|
-
* @param {Object} config 配置参数
|
|
5
|
-
*/
|
|
6
|
-
module.exports = function(server, config) {
|
|
7
|
-
var cos = config.cos;
|
|
8
|
-
if (cos && cos.status) {
|
|
9
|
-
if (cos.headers && cos.origin !== "*") {
|
|
10
|
-
/* 跨域限制(web防火墙) */
|
|
11
|
-
server.use(async (ctx, next) => {
|
|
12
|
-
try {
|
|
13
|
-
var req = ctx.request;
|
|
14
|
-
|
|
15
|
-
// 允许来自所有域名请求
|
|
16
|
-
ctx.set('Access-Control-Allow-Origin', cos.origin);
|
|
17
|
-
// 这样就能只允许 http://localhost:8080 这个域名的请求了
|
|
18
|
-
// ctx.set("Access-Control-Allow-Origin", "http://localhost:8080");
|
|
19
|
-
|
|
20
|
-
// 字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段.
|
|
21
|
-
if (req.method == "OPTIONS") {
|
|
22
|
-
ctx.set('Access-Control-Allow-Headers', cos.headers);
|
|
23
|
-
|
|
24
|
-
// 服务器收到请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。
|
|
25
|
-
// Content-Type表示具体请求中的媒体类型信息
|
|
26
|
-
// ctx.set("Content-Type", "application/json;charset=utf-8");
|
|
27
|
-
// 设置所允许的HTTP请求方法PUT,POST,GET,DELETE,HEAD,OPTIONS
|
|
28
|
-
// ctx.set('Access-Control-Allow-Methods', 'GET,POST');
|
|
29
|
-
|
|
30
|
-
// 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。
|
|
31
|
-
// 当设置成允许请求携带cookie时,需要保证"Access-Control-Allow-Origin"是服务器有的域名,而不能是"*";
|
|
32
|
-
// ctx.set("Access-Control-Allow-Credentials", 'false');
|
|
33
|
-
|
|
34
|
-
// 该字段可选,用来指定本次预检请求的有效期,单位为秒。
|
|
35
|
-
// 当请求方法是PUT或DELETE等特殊方法或者Content-Type字段的类型是application/json时,服务器会提前发送一次请求进行验证
|
|
36
|
-
// 下面的的设置只本次验证的有效时间,即在该时间段内服务端可以不用进行验证
|
|
37
|
-
// ctx.set("Access-Control-Max-Age", '3600');
|
|
38
|
-
/*
|
|
39
|
-
CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:
|
|
40
|
-
Cache-Control、
|
|
41
|
-
Content-Language、
|
|
42
|
-
Content-Type、
|
|
43
|
-
Expires、
|
|
44
|
-
Last-Modified、
|
|
45
|
-
Pragma
|
|
46
|
-
*/
|
|
47
|
-
// 需要获取其他字段时,使用Access-Control-Expose-Headers,
|
|
48
|
-
// getResponseHeader('myData')可以返回我们所需的值
|
|
49
|
-
// ctx.set("Access-Control-Expose-Headers", "myData");
|
|
50
|
-
ctx.status = 204;
|
|
51
|
-
} else {
|
|
52
|
-
await next();
|
|
53
|
-
}
|
|
54
|
-
} catch (error) {
|
|
55
|
-
$.log.error('CORS中间件错误(origin限制):', error);
|
|
56
|
-
// 出错时默认允许请求继续处理
|
|
57
|
-
await next();
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
} else if (cos.headers && cos.headers !== "*") {
|
|
61
|
-
/* 跨域限制(web防火墙) */
|
|
62
|
-
server.use(async (ctx, next) => {
|
|
63
|
-
try {
|
|
64
|
-
var req = ctx.request;
|
|
65
|
-
// 允许来自所有域名请求
|
|
66
|
-
ctx.set('Access-Control-Allow-Origin', '*');
|
|
67
|
-
// ctx.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
|
|
68
|
-
if (req.method === 'OPTIONS') {
|
|
69
|
-
ctx.set('Access-Control-Allow-Headers', cos.headers);
|
|
70
|
-
ctx.status = 204;
|
|
71
|
-
} else {
|
|
72
|
-
await next();
|
|
73
|
-
}
|
|
74
|
-
} catch (error) {
|
|
75
|
-
$.log.error('CORS中间件错误(headers限制):', error);
|
|
76
|
-
// 出错时默认允许请求继续处理
|
|
77
|
-
await next();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
/* 跨域限制(web防火墙) */
|
|
82
|
-
server.use(async (ctx, next) => {
|
|
83
|
-
try {
|
|
84
|
-
var req = ctx.request;
|
|
85
|
-
// 允许来自所有域名请求
|
|
86
|
-
ctx.set('Access-Control-Allow-Origin', '*');
|
|
87
|
-
// ctx.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
|
|
88
|
-
if (req.method === 'OPTIONS') {
|
|
89
|
-
ctx.set('Access-Control-Allow-Headers', '*');
|
|
90
|
-
ctx.status = 204;
|
|
91
|
-
} else {
|
|
92
|
-
await next();
|
|
93
|
-
}
|
|
94
|
-
} catch (error) {
|
|
95
|
-
$.log.error('CORS中间件错误(完全宽松):', error);
|
|
96
|
-
// 出错时默认允许请求继续处理
|
|
97
|
-
await next();
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return server;
|
|
103
|
-
};
|
package/middleware/log/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* web日志
|
|
3
|
-
* @param {Object} server 服务
|
|
4
|
-
* @param {Object} config 配置参数
|
|
5
|
-
*/
|
|
6
|
-
module.exports = function(server, config) {
|
|
7
|
-
/* 跨域限制(web防火墙) */
|
|
8
|
-
server.use(async (ctx, next) => {
|
|
9
|
-
try {
|
|
10
|
-
var url = ctx.path + ctx.querystring;
|
|
11
|
-
var body = "";
|
|
12
|
-
if (ctx.request.body) {
|
|
13
|
-
try {
|
|
14
|
-
body = JSON.stringify(ctx.request.body);
|
|
15
|
-
if (body.length > 1024) {
|
|
16
|
-
body = body.substring(0, 1024) + "..."
|
|
17
|
-
}
|
|
18
|
-
} catch (jsonError) {
|
|
19
|
-
body = "[无法序列化请求体]";
|
|
20
|
-
$.log.error('日志中间件JSON序列化错误:', jsonError);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
$.log.http(`${ctx.method}\t${url}\t${body}`);
|
|
24
|
-
await next();
|
|
25
|
-
} catch (error) {
|
|
26
|
-
$.log.error('log中间件错误:', error);
|
|
27
|
-
// 确保请求可以继续处理
|
|
28
|
-
await next();
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
return server;
|
|
32
|
-
};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API速率限制中间件
|
|
3
|
-
* 用于防止DoS攻击,限制客户端在一定时间内的请求频率
|
|
4
|
-
* @param {Object} server 服务实例
|
|
5
|
-
* @param {Object} config 配置参数
|
|
6
|
-
*/
|
|
7
|
-
module.exports = function(server, config) {
|
|
8
|
-
// 初始化速率限制配置
|
|
9
|
-
const cg = {
|
|
10
|
-
// 默认配置
|
|
11
|
-
windowMs: 60 * 1000, // 时间窗口,调整为1分钟(更精细的限制)
|
|
12
|
-
maxRequests: 5000, // 每个时间窗口内的最大请求数,从1000提高到5000
|
|
13
|
-
message: '请求过于频繁,请稍后再试', // 超过限制时的提示信息
|
|
14
|
-
statusCode: 429, // 超过限制时的HTTP状态码
|
|
15
|
-
// 白名单路径,这些路径不受速率限制
|
|
16
|
-
whitelistPaths: [],
|
|
17
|
-
// 合并用户配置
|
|
18
|
-
...(config && config.rate_limit ? config.rate_limit : {})
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// 生成基于IP的唯一标识符
|
|
22
|
-
function getClientKey(ctx) {
|
|
23
|
-
// 优先使用X-Forwarded-For头部(如果有代理的话)
|
|
24
|
-
const forwardedFor = ctx.headers['x-forwarded-for'];
|
|
25
|
-
if (forwardedFor) {
|
|
26
|
-
// 通常格式为:X-Forwarded-For: client, proxy1, proxy2
|
|
27
|
-
return forwardedFor.split(',')[0].trim();
|
|
28
|
-
}
|
|
29
|
-
// 直接使用IP地址
|
|
30
|
-
return ctx.ip;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 使用Redis存储请求计数
|
|
34
|
-
async function incrementRequestWithRedis(clientKey) {
|
|
35
|
-
try {
|
|
36
|
-
// 检查Redis是否可用
|
|
37
|
-
if ($.cache && typeof $.cache.addInt === 'function') {
|
|
38
|
-
const key = `rate_limit:${clientKey}`;
|
|
39
|
-
|
|
40
|
-
// 使用addInt方法增加计数(mm_redis包提供的方法)
|
|
41
|
-
const count = await $.cache.addInt(key, 1);
|
|
42
|
-
|
|
43
|
-
// 设置过期时间
|
|
44
|
-
await $.cache.ttl(key, Math.ceil(cg.windowMs / 1000));
|
|
45
|
-
|
|
46
|
-
return count || 0;
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
$.log.error('Redis速率限制失败:', error);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Redis不可用时返回null,将使用内存存储
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 中间件主逻辑
|
|
57
|
-
server.use(async (ctx, next) => {
|
|
58
|
-
try {
|
|
59
|
-
// 跳过静态文件和favicon请求
|
|
60
|
-
if (ctx.path === '/favicon.ico' || ctx.path.startsWith('/static/')) {
|
|
61
|
-
await next();
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// 检查是否是白名单路径
|
|
66
|
-
if (cg.whitelistPaths && cg.whitelistPaths.some(path =>
|
|
67
|
-
ctx.path === path || ctx.path.startsWith(path + '/'))) {
|
|
68
|
-
await next();
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 获取客户端唯一标识符
|
|
73
|
-
const clientKey = getClientKey(ctx);
|
|
74
|
-
|
|
75
|
-
let requestCount = await incrementRequestWithRedis(clientKey);
|
|
76
|
-
|
|
77
|
-
// 设置响应头部,告知客户端当前的限制状态
|
|
78
|
-
ctx.set('X-RateLimit-Limit', cg.maxRequests);
|
|
79
|
-
ctx.set('X-RateLimit-Remaining', Math.max(0, cg.maxRequests - requestCount));
|
|
80
|
-
|
|
81
|
-
// 检查是否超过限制
|
|
82
|
-
if (requestCount > cg.maxRequests) {
|
|
83
|
-
$.log.warn(`API速率限制触发: ${clientKey} 请求 ${ctx.path} 次数过多`);
|
|
84
|
-
|
|
85
|
-
ctx.status = cg.statusCode;
|
|
86
|
-
ctx.body = {
|
|
87
|
-
code: cg.statusCode,
|
|
88
|
-
msg: cg.message
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// 记录超过限制的请求
|
|
92
|
-
if ($.log && $.log.warn) {
|
|
93
|
-
$.log.warn(`速率限制触发: IP=${clientKey}, Path=${ctx.path}, Method=${ctx.method}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// 继续处理请求
|
|
100
|
-
await next();
|
|
101
|
-
} catch (error) {
|
|
102
|
-
$.log.error('速率限制中间件错误:', error);
|
|
103
|
-
// 确保请求可以继续处理
|
|
104
|
-
await next();
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// 记录中间件初始化信息
|
|
109
|
-
$.log.info(`速率限制中间件已加载: ${cg.maxRequests}请求/${cg.windowMs/1000}秒`);
|
|
110
|
-
|
|
111
|
-
return server;
|
|
112
|
-
};
|
package/nodemon.json
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"restartable": "rs",
|
|
3
|
-
"ignore": [
|
|
4
|
-
".git",
|
|
5
|
-
".svn",
|
|
6
|
-
"cache",
|
|
7
|
-
"log",
|
|
8
|
-
"node_modules/**/node_modules",
|
|
9
|
-
"**/cache/**",
|
|
10
|
-
"game/data",
|
|
11
|
-
"**/conf.json",
|
|
12
|
-
"*/static/*/*.json",
|
|
13
|
-
"*/static/*.js"
|
|
14
|
-
],
|
|
15
|
-
"verbose": true,
|
|
16
|
-
"execMap": {
|
|
17
|
-
"": "node",
|
|
18
|
-
"js": "node --harmony"
|
|
19
|
-
},
|
|
20
|
-
"watch": [
|
|
21
|
-
"demo",
|
|
22
|
-
"lib",
|
|
23
|
-
"core",
|
|
24
|
-
"test"
|
|
25
|
-
],
|
|
26
|
-
"env": {
|
|
27
|
-
"NODE_ENV": "development"
|
|
28
|
-
},
|
|
29
|
-
"ext": "js ts json",
|
|
30
|
-
"legacy-watch": false
|
|
31
|
-
}
|
package/package.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
mm_check mm_excel mm_expand mm_html mm_koa_proxy mm_logs mm_machine mm_mongodb mm_mqtt mm_mysql mm_redis mm_ret mm_session mm_statics mm_tpl mm_xml
|
package/rps.bat
DELETED
package/test.js
DELETED
package/tps.bat
DELETED
package/update.bat
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
npm i mm_check mm_excel mm_expand mm_html mm_koa_proxy mm_logs mm_machine mm_mongodb mm_mqtt mm_mysql mm_redis mm_ret mm_session mm_statics mm_tpl mm_xml
|