Skip to content

Commit 2adeb68

Browse files
committed
Java:MultiDataSource 中 SQLAuto: 强校验 SQL 实际影响数量;代理接口:兼容不同 Header, Body 传参及 query 转义
1 parent 37481e7 commit 2adeb68

1 file changed

Lines changed: 37 additions & 21 deletions

File tree

APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/boot/DemoController.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,13 @@ else if (names != null) {
16531653
String k = ind < 0 ? kv : kv.substring(0, ind);
16541654
Object v = ind < 0 ? null : kv.substring(ind + 1);
16551655

1656+
// query 已经转义
1657+
// try {
1658+
// v = URLDecoder.decode((String) v, StringUtil.UTF_8);
1659+
// } catch (Throwable e) {
1660+
// e.printStackTrace();
1661+
// }
1662+
16561663
try {
16571664
v = JSON.parse(v);
16581665
} catch (Throwable e) {
@@ -1821,11 +1828,11 @@ else if (recordType > 0) {
18211828
JSONObject document = JSON.newJSONObject();
18221829
document.put("from", 2); // 0-测试工具,1-CI/CD,2-流量录制
18231830
document.put("name", "[Record] " + new java.util.Date().toLocaleString());
1824-
document.put("type", reqType);
18251831
document.put("method", method == null ? "GET" : method.name());
1832+
document.put("type", reqType);
18261833
document.put("url", branch);
18271834
document.put("header", StringUtil.isEmpty(hs, true) ? null : hs.trim());
1828-
document.put("request", isSQL ? "{}" : (reqBody != null && ! reqBody.isEmpty() ? JSON.toJSONString(reqBody) : (StringUtil.isEmail(body) ? "{}" : body)));
1835+
document.put("request", isSQL ? "{}" : (reqBody != null && ! reqBody.isEmpty() ? JSON.toJSONString(reqBody) : (StringUtil.isEmpty(body) ? "{}" : body)));
18291836
if (isSQL) {
18301837
// 没有名称,除非 args 传对象而不是数组
18311838
// JSONList args = req.getJSONArray("args");
@@ -1849,7 +1856,7 @@ else if (recordType > 0) {
18491856
}
18501857
else {
18511858
// Random <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1852-
Map<String, ?> m = isSQL ? null : reqBody;
1859+
Map<String, ?> m = isSQL ? null : (reqBody != null && ! reqBody.isEmpty() ? reqBody : (isBodyEmpty ? map : JSON.parseObject(body)));
18531860
String config = isSQL ? hs : parseRandomConfig("", m);
18541861

18551862
JSONObject random = JSON.newJSONObject();
@@ -2021,8 +2028,9 @@ protected Long getContentLength(String s, MediaType contentType) {
20212028
protected String sendRequest(HttpSession session, HttpMethod method, String url, String body, HttpHeaders headers) {
20222029
String rspBody = null;
20232030
try {
2024-
// 为JSON请求设置默认的Content-Type
2025-
if (body != null && method != HttpMethod.GET && !headers.containsKey(HttpHeaders.CONTENT_TYPE)) {
2031+
// 为JSON请求设置默认的 Content-Type
2032+
boolean hasContentType = headers.containsKey(HttpHeaders.CONTENT_TYPE) || headers.containsKey(HttpHeaders.CONTENT_TYPE.toLowerCase());
2033+
if (body != null && method != HttpMethod.GET && ! hasContentType) {
20262034
// 尝试解析JSON来判断内容类型
20272035
try {
20282036
JSON.parse(body);
@@ -2034,13 +2042,13 @@ protected String sendRequest(HttpSession session, HttpMethod method, String url,
20342042
}
20352043

20362044
// 设置默认的Accept header
2037-
if (!headers.containsKey(HttpHeaders.ACCEPT)) {
2045+
if (! (headers.containsKey(HttpHeaders.ACCEPT) || headers.containsKey(HttpHeaders.ACCEPT.toLowerCase()))) {
20382046
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
20392047
}
20402048

20412049
// 为大文本body,设置适当的Content-Type和分块传输
20422050
if (body != null && body.length() > 1024 * 1024) { // 超过1MB
2043-
if (!headers.containsKey(HttpHeaders.CONTENT_TYPE)) {
2051+
if (! hasContentType) {
20442052
headers.setContentType(MediaType.TEXT_PLAIN);
20452053
}
20462054
// 设置分块传输
@@ -2094,8 +2102,11 @@ protected String sendRequest(HttpSession session, HttpMethod method, String url,
20942102
}
20952103
}
20962104

2097-
SESSION_MAP.put(session.getId(), session);
2098-
httpServletResponse.setHeader(APIJSON_DELEGATE_ID, session.getId());
2105+
String id = session == null ? null : session.getId();
2106+
if (id != null) {
2107+
SESSION_MAP.put(id, session);
2108+
httpServletResponse.setHeader(APIJSON_DELEGATE_ID, id);
2109+
}
20992110

21002111
return rspBody;
21012112
}
@@ -2425,13 +2436,13 @@ public String execute(@RequestBody String request, HttpSession session) {
24252436
} else if (sqlRest.startsWith("`" + userIdKey + "`") || sqlRest.startsWith("[" + userIdKey + "]") || sqlRest.startsWith("\"" + userIdKey + "\"")) {
24262437
key = "`" + userIdKey + "`";
24272438
} else {
2428-
throw new IllegalArgumentException("SQL WHERE 后必须接着 "+ idKey + " 或 " + idKey + " = ? 或 IN(?,?..) !");
2439+
throw new IllegalArgumentException("SQL WHERE 后必须接着 "+ idKey + " 或 " + userIdKey + " = ? 或 IN(?, ? ...) !");
24292440
}
24302441

24312442
sqlRest = sqlRest.substring(key.length()).trim();
24322443
boolean isEq = sqlRest.startsWith("=");
24332444
if (! (isEq || sqlRest.startsWith("IN(") || sqlRest.startsWith("in("))) {
2434-
throw new IllegalArgumentException("SQL WHERE "+ key + " 后必须接着 = ? 或 IN(?, ? ...) ! ");
2445+
throw new IllegalArgumentException("SQL WHERE " + key + " 后必须接着 = ? 或 IN(?, ? ...) ! ");
24352446
}
24362447

24372448
sqlRest = sqlRest.substring(isEq ? 1 : "IN(".length()).trim();
@@ -2486,21 +2497,20 @@ public String execute(@RequestBody String request, HttpSession session) {
24862497
//
24872498
//}
24882499

2489-
List<Map<String, Object>> find = null;
2500+
List<Map<String, Object>> list = null;
24902501
Set<Entry<String, List<Map<String, Object>>>> set = sqlautoMap == null ? null : sqlautoMap.entrySet();
24912502
if (set != null) {
24922503
for (Entry<String, List<Map<String, Object>>> entry : set) {
24932504
String sqlauto = StringUtil.trim(entry == null ? null : entry.getKey());
2494-
List<Map<String, Object>> list = sqlauto.equalsIgnoreCase(trimmedSQL) ? entry.getValue() : null;
2505+
list = sqlauto.equalsIgnoreCase(trimmedSQL) ? entry.getValue() : null;
24952506
if (list != null && ! list.isEmpty()) {
2496-
find = list;
2497-
Log.d(TAG, "execute " + sql + " : find match rows = " + JSON.toJSONString(find, true));
2507+
Log.d(TAG, "execute " + sql + " : find match rows = " + JSON.toJSONString(list, true));
24982508
break;
24992509
}
25002510
}
25012511
}
25022512

2503-
if (find == null) {
2513+
if (list == null || list.isEmpty()) {
25042514
throw new IllegalAccessException("严格模式下 DELETE/UPDATE SQL 只允许 Document 表 sqlauto 字段值,请提前写入并刷新后端服务配置!");
25052515
}
25062516
}
@@ -2523,6 +2533,9 @@ public String execute(@RequestBody String request, HttpSession session) {
25232533
if ("?".endsWith(as)) {
25242534
int j = arg == null ? -1 : arg.size() - (arr.length - i);
25252535
as = j < 0 || j > arg.size() ? null : arg.getString(j);
2536+
if (StringUtil.isEmail(as)) {
2537+
throw new IllegalArgumentException("SQL LIMIT ? 对应的 args[" + j + "] = " + as + " 不合法!");
2538+
}
25262539
}
25272540

25282541
try {
@@ -2580,8 +2593,8 @@ public String execute(@RequestBody String request, HttpSession session) {
25802593
connection.setAutoCommit(false);
25812594
// connection.beginRequest();
25822595
int rows = ((PreparedStatement) statement).executeUpdate();
2583-
if (rows >= maxCount) {
2584-
throw new UnsupportedOperationException("实际影响数量超过上限 " + maxCount + " ! 已回滚变更");
2596+
if (rows > maxCount) {
2597+
throw new UnsupportedOperationException("实际影响数量 " + rows + " 超过上限 " + maxCount + " ! 已回滚变更");
25852598
}
25862599
} catch (Throwable e) {
25872600
connection.rollback();
@@ -2595,7 +2608,7 @@ public String execute(@RequestBody String request, HttpSession session) {
25952608
}
25962609
} else {
25972610
if (arg != null && ! arg.isEmpty()) {
2598-
throw new UnsupportedOperationException("非预编译模式不允许传参 arg !");
2611+
throw new UnsupportedOperationException("非预编译模式不允许传参 args !");
25992612
}
26002613

26012614
if (EXECUTE_STRICTLY) {
@@ -2604,8 +2617,8 @@ public String execute(@RequestBody String request, HttpSession session) {
26042617
connection.setAutoCommit(false);
26052618
// connection.beginRequest();
26062619
int rows = statement.executeUpdate(sql);
2607-
if (rows >= maxCount) {
2608-
throw new UnsupportedOperationException("实际影响数量超过上限 " + maxCount + " ! 已回滚变更");
2620+
if (rows > maxCount) {
2621+
throw new UnsupportedOperationException("实际影响数量 " + rows + " 超过上限 " + maxCount + " ! 已回滚变更");
26092622
}
26102623
} catch (Throwable e) {
26112624
connection.rollback();
@@ -2646,6 +2659,9 @@ public String execute(@RequestBody String request, HttpSession session) {
26462659

26472660
// try {
26482661
updateCount = statement.getUpdateCount();
2662+
if (WRITE_STRICTLY && isWrite && updateCount > maxCount) {
2663+
throw new IllegalArgumentException("实际影响数量 " + updateCount + " 超过上限 " + maxCount + " ! 已回滚变更");
2664+
}
26492665
// } catch (Throwable e) {
26502666
// e.printStackTrace();
26512667
// }

0 commit comments

Comments
 (0)