doomiwork 3.5.5 → 3.6.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/package.json
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
const keyParse = require('./keywordparse');
|
|
3
3
|
const dataconfig = require('../configuration/dataconfig').getCurrent();
|
|
4
4
|
const mysql = require('mysql');
|
|
5
|
+
const ORDER_STRING= ['asc','desc']
|
|
6
|
+
const FORBID_SQL_KEYWORD = /;|(--)|(\bWHERE\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
|
|
7
|
+
// const FORBID_SQL_KEYWORD_STRICT = /;|(--)|(\bOR\b)|(\bAND\b)|(\bWHERE\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
|
|
8
|
+
|
|
5
9
|
class RequestParser {
|
|
6
10
|
/*
|
|
7
11
|
* 根据对应列表的配置(dataConfig.list.search),从请求上下文中获取用户进行搜索的参数信息
|
|
@@ -11,11 +15,11 @@ class RequestParser {
|
|
|
11
15
|
if (!paraCopy.request || !paraCopy.refer) return '';
|
|
12
16
|
if (!paraCopy.valueFrom) paraCopy.valueFrom = "all";
|
|
13
17
|
const request = paraCopy.request;
|
|
14
|
-
let retSearch =
|
|
15
|
-
paraCopy.refer.forEach(element=> {
|
|
16
|
-
retSearch
|
|
18
|
+
let retSearch = [];
|
|
19
|
+
paraCopy.refer.forEach(element => {
|
|
20
|
+
retSearch.push(this.parseAndReplaceSql(request, element.pattern, false));
|
|
17
21
|
});
|
|
18
|
-
return retSearch;
|
|
22
|
+
return retSearch.join('');
|
|
19
23
|
}
|
|
20
24
|
/*
|
|
21
25
|
解析sql字符串中特殊的占位符
|
|
@@ -25,18 +29,31 @@ class RequestParser {
|
|
|
25
29
|
///定义正则准备查找sql中的特定关键字
|
|
26
30
|
const matched=sql.match(/@.*?@/g);
|
|
27
31
|
if (!matched || matched.length<=0) return sql;
|
|
28
|
-
|
|
32
|
+
let parseKeyWordIsNull = false;
|
|
33
|
+
|
|
34
|
+
const charReg = /\s+|:|=/gi
|
|
29
35
|
matched.forEach(ele=>{
|
|
30
36
|
let matchValue = ele.substring(1,ele.length-1);
|
|
31
|
-
|
|
32
|
-
let
|
|
33
|
-
if(
|
|
37
|
+
///不允许特殊字符出现
|
|
38
|
+
let notdo = matchValue.match(charReg);
|
|
39
|
+
if (notdo && notdo.length>0)return;
|
|
40
|
+
|
|
41
|
+
//if (matchValue.indexOf(' ')>=0 || matchValue.indexOf(':')>=0 || matchValue.indexOf('=')>=0) return;
|
|
42
|
+
let noQuoteProtect = matchValue[0] == '!';
|
|
43
|
+
if (noQuoteProtect){
|
|
44
|
+
matchValue = matchValue.substring(1);
|
|
45
|
+
}
|
|
46
|
+
let keyValue = utility.ifNull(keyParse.parseKeyValue(req, matchValue),'');
|
|
47
|
+
if(!keyValue) {
|
|
34
48
|
parseKeyWordIsNull = true;
|
|
35
49
|
}else if (typeof(keyValue)==='string'){
|
|
36
|
-
keyValue = mysql.escape(keyValue)
|
|
37
|
-
keyValue = keyValue.substr(1, keyValue.length - 2)
|
|
50
|
+
keyValue = noQuoteProtect ? this.checkSqlInjection(mysql.escape(keyValue)):mysql.escape(keyValue)
|
|
51
|
+
keyValue = keyValue.substr(1, keyValue.length - 2);
|
|
52
|
+
///没有引号保护下发现了sql注入,则用1=0不返回任何结果
|
|
53
|
+
if (!keyValue && noQuoteProtect) {
|
|
54
|
+
keyValue = '1=0'
|
|
55
|
+
}
|
|
38
56
|
}
|
|
39
|
-
|
|
40
57
|
sql=sql.replace(ele,keyValue);
|
|
41
58
|
});
|
|
42
59
|
if (!allowNull && parseKeyWordIsNull) return '';
|
|
@@ -49,7 +66,16 @@ class RequestParser {
|
|
|
49
66
|
return originSql.replace('#APPENDSEARCH#',searchCondition);
|
|
50
67
|
return originSql + ' '+ searchCondition;
|
|
51
68
|
}
|
|
52
|
-
|
|
69
|
+
/**
|
|
70
|
+
* 检查是否有Sql注入的风险
|
|
71
|
+
* @param {*} sql
|
|
72
|
+
*/
|
|
73
|
+
static checkSqlInjection(sql){
|
|
74
|
+
if(!sql) return sql;
|
|
75
|
+
let sqlError = sql.match(FORBID_SQL_KEYWORD); //strict ? sql.match(FORBID_SQL_KEYWORD_STRICT):sql.match(FORBID_SQL_KEYWORD);
|
|
76
|
+
if (sqlError && sqlError.length>0) return '';
|
|
77
|
+
return sql;
|
|
78
|
+
}
|
|
53
79
|
/*
|
|
54
80
|
* 列表请求上下文中获取需要的信息
|
|
55
81
|
* 如Page ,PageSize , Sort 等等
|
|
@@ -61,6 +87,11 @@ class RequestParser {
|
|
|
61
87
|
req.page = req.query.page || req.body.page|| 1;
|
|
62
88
|
req.pageSize = req.query.rows || req.body.rows || 100;
|
|
63
89
|
req.sort = req.query.sort || req.body.sort;
|
|
90
|
+
///防止sortSql 注入
|
|
91
|
+
///防止sortSql 注入
|
|
92
|
+
if (req.sort) {
|
|
93
|
+
req.sort = this.checkSqlInjection(req.sort);
|
|
94
|
+
}
|
|
64
95
|
//防止注入式Sql
|
|
65
96
|
if (isNaN(req.pageSize)){
|
|
66
97
|
req.pageSize = 30;
|
|
@@ -71,7 +102,13 @@ class RequestParser {
|
|
|
71
102
|
}
|
|
72
103
|
///最大允许获取100条数据
|
|
73
104
|
req.pageSize = Math.min(req.pageSize,100);
|
|
74
|
-
|
|
105
|
+
let order = (req.body.order || req.query.order || '').trim().toLowerCase();
|
|
106
|
+
if (order && req.sort){
|
|
107
|
+
if (ORDER_STRING.indexOf(order)>=0) {
|
|
108
|
+
req.sort = req.sort + ' ' + order
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//req.order =req.sort? utility.ifNull((req.body.order || req.query.order), ""):'';
|
|
75
112
|
if (dataKey) {
|
|
76
113
|
req.dataConfig = dataconfig.getConfig(dataKey,cfgType);
|
|
77
114
|
if (req.dataConfig && req.dataConfig.list) {
|
|
@@ -83,7 +120,8 @@ class RequestParser {
|
|
|
83
120
|
/**排序方式 */
|
|
84
121
|
req.sort = req.sort || req.dataConfig.list.sort;
|
|
85
122
|
/**来自req请求参数中的过滤条件 */
|
|
86
|
-
let clientFilter = this.parseAndReplaceSql(req,req.query.clientFilter);
|
|
123
|
+
let clientFilter = this.checkSqlInjection(this.parseAndReplaceSql(req,req.query.clientFilter),false);
|
|
124
|
+
|
|
87
125
|
let listsql='';
|
|
88
126
|
///是否有列表尾部的统计SQL
|
|
89
127
|
let countsql = '';
|
|
@@ -106,7 +144,8 @@ class RequestParser {
|
|
|
106
144
|
/**根据过滤条件、排序条件、分页获取的方式,和原始sql拼接成最终获取数据的sql */
|
|
107
145
|
req.listSql = this.parseAndReplaceSql(req,listsql) +
|
|
108
146
|
' ' + req.searchCondition + clientFilter +
|
|
109
|
-
(utility.isNullOrEmpty(req.sort) ? '' : (' order by ' + (req.sort+' '+req.order))) +
|
|
147
|
+
//(utility.isNullOrEmpty(req.sort) ? '' : (' order by ' + (req.sort+' '+req.order))) +
|
|
148
|
+
(req.sort ? (' order by ' + req.sort ):'') +
|
|
110
149
|
(export2Excel?'':' limit ' + req.pageSize + ' OFFSET ' + (req.page - 1) * req.pageSize) +
|
|
111
150
|
/////在Sql中再放入获取总记录数的语句
|
|
112
151
|
';SELECT FOUND_ROWS() AS total;';
|
|
@@ -75,7 +75,7 @@ class ViewHelper {
|
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
77
|
//验证值的类型是否正确,主要验证是否数字
|
|
78
|
-
if(element.type){
|
|
78
|
+
if (element.type && postValue){
|
|
79
79
|
switch (element.type.toLowerCase()){
|
|
80
80
|
case 'number': ///验证是否是数字
|
|
81
81
|
if (isNaN(postValue)) return { successed: false, errcode: 4, errmsg: '字段类型错误(Number)', name: element.mapping }
|