Skip to content

Commit 8b5624d

Browse files
committed
Java:MultiDataSource 中 SQLAuto 新增支持只允许传 Document 配置的 sqlauto 值作为 DELETE/UPDATE SQL 的严格写入模式
1 parent 5dad43b commit 8b5624d

2 files changed

Lines changed: 129 additions & 4 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public static void main(String[] args) throws Exception {
9494
//APIJSONParser.IS_START_FROM_1 = true; // 分页页码是否从 1 开始,true - 从 1 开始;false - 从 0 开始
9595
APIJSONSQLConfig.ENABLE_COLUMN_CONFIG = false; // apijson-framework 已集成字段插件 apijson-column,支持 !key 反选字段 和 字段名映射
9696
APIJSONApplication.init();
97+
DemoController.init();
9798
System.out.println("\n\n<<<<<<<<< 本 Demo 在 resources/static 内置了 APIAuto,Chrome/Firefox 打开 http://localhost:8080 即可调试(端口号根据项目配置而定) ^_^ >>>>>>>>>\n");
9899
}
99100

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

Lines changed: 128 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import apijson.fastjson2.APIJSONController;
1818
import apijson.fastjson2.APIJSONParser;
1919
import apijson.fastjson2.JSONRequest;
20+
import apijson.framework.APIJSONApplication;
21+
import apijson.framework.APIJSONConstant;
22+
import apijson.framework.APIJSONCreator;
2023
import apijson.orm.exception.*;
2124
import com.alibaba.fastjson2.JSONArray;
2225
import com.alibaba.fastjson2.JSONObject;
@@ -105,6 +108,7 @@
105108
public class DemoController extends APIJSONController<Long> {
106109
private static final String TAG = "DemoController";
107110

111+
108112
public String getRequestBaseURL() {
109113
HttpServletRequest httpReq = httpServletRequest;
110114
String host = httpReq.getHeader("origin");
@@ -2155,7 +2159,102 @@ private String parseRandomConfig(String path, Object obj) {
21552159
return config;
21562160
}
21572161

2162+
public static void onServerError(String msg, boolean shutdown) throws ServerException {
2163+
Log.e("DemoController", "\nSQLAuto 测试未通过!\n请修改 Document 表里的 sqlauto 为合法的 SQL 语句!\n\n原因:\n" + msg);
2164+
if (shutdown) {
2165+
System.exit(1);
2166+
} else {
2167+
throw new ServerException(msg);
2168+
}
2169+
}
2170+
21582171
public static boolean EXECUTE_STRICTLY = true;
2172+
public static boolean WRITE_STRICTLY = EXECUTE_STRICTLY;
2173+
2174+
public static Map<String, List<Map<String, Object>>> SQLAUTO_MAP;
2175+
static {
2176+
SQLAUTO_MAP = new LinkedHashMap<>();
2177+
}
2178+
public static void init() throws ServerException {
2179+
init(true, null, null);
2180+
}
2181+
public static void init(boolean shutdownWhenServerError, APIJSONCreator<?, ? extends Map<String, Object>, ? extends List<Object>> creator, JSONObject table) throws ServerException {
2182+
if (creator == null) {
2183+
creator = APIJSONApplication.DEFAULT_APIJSON_CREATOR;
2184+
}
2185+
2186+
boolean isAll = table == null || table.isEmpty();
2187+
//JSONObject document = isAll ? JSON.createJSONObject((new JSONRequest("sqlauto{}", "length(sqlauto)>0")).setOrder("version-,id+")) : table;
2188+
JSONObject document = isAll ? JSON.createJSONObject((new JSONRequest("sqlauto$", Arrays.asList("UPDATE %", "DELETE %"))).setOrder("version-,id+")) : table;
2189+
if (!Log.DEBUG) {
2190+
document.put(APIJSONConstant.KEY_DEBUG, 0);
2191+
}
2192+
2193+
JSONObject requestItem = JSON.createJSONObject();
2194+
requestItem.put(APIJSONConstant.DOCUMENT_, document);
2195+
requestItem.put("count", 0);
2196+
JSONObject request = new JSONObject();
2197+
request.put(APIJSONConstant.DOCUMENT_ + "[]", requestItem);
2198+
Map<String, Object> response = creator.createParser().setMethod(GET).setNeedVerify(false).parseResponse(request.toJSONString());
2199+
if (! JSONResponse.isSuccess(response)) {
2200+
Log.e(TAG, "\n\n\n\n\n !!!! 查询请求映射配置异常 !!!\n" + JSON.getString(response, "msg") + "\n\n\n\n\n");
2201+
onServerError("查询请求映射配置异常 !", shutdownWhenServerError);
2202+
}
2203+
2204+
JSONArray list = JSON.getJSONArray(response, APIJSONConstant.DOCUMENT_ + "[]");
2205+
int size = list == null ? 0 : list.size();
2206+
if (isAll && size <= 0) {
2207+
Log.w(TAG, "init isAll && size <= 0,没有可用的请求映射配置");
2208+
return;
2209+
}
2210+
Log.d(TAG, "init < for SQLAUTO_MAP.size() = " + SQLAUTO_MAP.size() + " <<<<<<<<<<<<<<<<<<<<<<<<");
2211+
Map<String, List<Map<String, Object>>> newMap = new LinkedHashMap<>();
2212+
2213+
for (int i = 0; i < size; i++) {
2214+
JSONObject item = JSON.getJSONObject(list, i);
2215+
if (item == null || item.isEmpty()) {
2216+
continue;
2217+
}
2218+
2219+
String version = JSON.getString(item, "version");
2220+
if (StringUtil.isEmpty(version, true)) {
2221+
onServerError("服务器内部错误,Document 表中的 id=" + JSON.getString(item, "id") + ", name=" + JSON.getString(item, "name") + " 对应 version 不能为空!", shutdownWhenServerError);
2222+
}
2223+
2224+
String url = JSON.getString(item, "url");
2225+
int index = url == null ? -1 : url.indexOf("/");
2226+
if (index != 0) {
2227+
onServerError("服务器内部错误,Document 表中的 id=" + JSON.getString(item, "id") + ", name=" + JSON.getString(item, "name") + ", url=" + url + " 对应 url 值错误,必须以 / 开头!", shutdownWhenServerError);
2228+
}
2229+
2230+
//String requestStr = JSON.getString(item, "request");
2231+
String sqlauto = JSON.getString(item, "sqlauto");
2232+
if (StringUtil.isEmpty(sqlauto)) {
2233+
//if (! StringUtil.isBranchUrl(url)) {
2234+
// onServerError("服务器内部错误,Document 表中的 id=" + JSON.getString(item, "id") + ", name=" + JSON.getString(item, "name") + ", url=" + url + " 对应 url 值错误!只允许合法的 URL 格式!", shutdownWhenServerError);
2235+
//}
2236+
} else {
2237+
sqlauto = StringUtil.trim(sqlauto);
2238+
List<Map<String, Object>> mapList = newMap.get(sqlauto);
2239+
if (mapList == null) {
2240+
mapList = new ArrayList<>();
2241+
newMap.put(sqlauto, mapList);
2242+
}
2243+
mapList.add(item);
2244+
}
2245+
2246+
}
2247+
2248+
if (isAll) {
2249+
SQLAUTO_MAP = newMap;
2250+
} else {
2251+
SQLAUTO_MAP.putAll(newMap);
2252+
}
2253+
2254+
Log.d(TAG, "init for /> SQLAUTO_MAP.size() = " + SQLAUTO_MAP.size() + " >>>>>>>>>>>>>>>>>>>>>>>");
2255+
}
2256+
2257+
21592258
/**执行 SQL 语句,支持 SQLAuto,注意仅仅不要开放给后端组外的任何人,更不要暴露到公司外的公网!
21602259
* @param request 只用String,避免encode后未decode
21612260
* @return
@@ -2230,9 +2329,37 @@ public String execute(@RequestBody String request, HttpSession session) {
22302329
}
22312330
}
22322331

2233-
22342332
String trimmedSQL = sql == null ? null : sql.trim();
22352333

2334+
String sqlPrefix = trimmedSQL == null || trimmedSQL.length() < 7 ? "" : trimmedSQL.substring(0, 7).toUpperCase();
2335+
boolean isInsert = sqlPrefix.startsWith("INSERT ");
2336+
boolean isWrite = isInsert || sqlPrefix.startsWith("UPDATE ") || sqlPrefix.startsWith("DELETE ");
2337+
if (WRITE_STRICTLY && isWrite && ! isInsert) {
2338+
// 只包含筛选出 apijson 字段的 Map<String, SortedMap<Integer, Map<String, Object>>> documemtMap = DemoVerifier.DOCUMENT_MAP;
2339+
Map<String, List<Map<String, Object>>> sqlautoMap = SQLAUTO_MAP;
2340+
//if (sqlautoMap == null || sqlautoMap.isEmpty()) {
2341+
//
2342+
//}
2343+
2344+
List<Map<String, Object>> find = null;
2345+
Set<Entry<String, List<Map<String, Object>>>> set = sqlautoMap == null ? null : sqlautoMap.entrySet();
2346+
if (set != null) {
2347+
for (Entry<String, List<Map<String, Object>>> entry : set) {
2348+
String sqlauto = StringUtil.trim(entry == null ? null : entry.getKey());
2349+
List<Map<String, Object>> list = sqlauto.equalsIgnoreCase(trimmedSQL) ? entry.getValue() : null;
2350+
if (list != null && ! list.isEmpty()) {
2351+
find = list;
2352+
Log.d(TAG, "execute find DELETE/UPDATE rows = " + JSON.toJSONString(find, true));
2353+
break;
2354+
}
2355+
}
2356+
}
2357+
2358+
if (find == null) {
2359+
throw new IllegalAccessException("严格模式下 DELETE/UPDATE SQL 只允许 Document 表 sqlauto 字段值,请提前写入并刷新后端服务配置!");
2360+
}
2361+
}
2362+
22362363
List<Object> valueList = arg;
22372364

22382365
DemoSQLExecutor executor = new DemoSQLExecutor();
@@ -2247,9 +2374,6 @@ public String execute(@RequestBody String request, HttpSession session) {
22472374
config.setPreparedValueList(valueList);
22482375
config.setSql(sql);
22492376

2250-
String sqlPrefix = trimmedSQL == null || trimmedSQL.length() < 7 ? "" : trimmedSQL.substring(0, 7).toUpperCase();
2251-
boolean isWrite = sqlPrefix.startsWith("INSERT ") || sqlPrefix.startsWith("UPDATE ") || sqlPrefix.startsWith("DELETE ");
2252-
22532377
JSONArray arr = null;
22542378

22552379
long updateCount = 0;

0 commit comments

Comments
 (0)