Skip to content

Commit 00f7961

Browse files
committed
解决 @column:"toId;(parentId)" 等写法可能绕过字段插件的校验
1 parent 89079f9 commit 00f7961

File tree

1 file changed

+59
-10
lines changed

1 file changed

+59
-10
lines changed

src/main/java/apijson/column/ColumnUtil.java

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public static void init() {
180180
* @return
181181
*/
182182
public static List<String> compatInputColumn(List<String> columns, String table, RequestMethod method) {
183-
return compatInputColumn(columns, table, method, null);
183+
return compatInputColumn(columns, table, method, null, false);
184184
}
185185

186186
/**适配请求参数 JSON 中 @column:value 的 value 中的 key。支持 !key 反选字段 和 字段名映射
@@ -196,7 +196,7 @@ public AbstractSQLConfig setColumn(List<String> column) { <br>
196196
}
197197
* </pre>
198198
*/
199-
public static List<String> compatInputColumn(List<String> columns, String table, RequestMethod method, Integer version) {
199+
public static List<String> compatInputColumn(List<String> columns, String table, RequestMethod method, Integer version, boolean throwWhenNoKey) {
200200
String[] keys = columns == null ? null : columns.toArray(new String[]{}); // StringUtil.split(c, ";");
201201
if (keys == null || keys.length <= 0) { // JOIN 副表可以设置 @column:"" 来指定不返回字段
202202
return columns != null ? columns : getClosestValue(VERSIONED_TABLE_COLUMN_MAP, version, table);
@@ -208,15 +208,47 @@ public static List<String> compatInputColumn(List<String> columns, String table,
208208
List<String> newColumns = new ArrayList<>();
209209

210210
Map<String, String> keyColumnMap = getClosestValue(VERSIONED_KEY_COLUMN_MAP, version, table);
211+
boolean isEmpty = keyColumnMap == null || keyColumnMap.isEmpty();
212+
213+
String q = "`";
211214

212215
String expression;
213216
//...;fun0(arg0,arg1,...):fun0;fun1(arg0,arg1,...):fun1;...
214217
for (int i = 0; i < keys.length; i++) {
215218

216219
//!column,column2,!column3,column4:alias4;fun(arg0,arg1,...)
217220
expression = keys[i];
218-
if (expression.contains("(") || expression.contains(")")) {
219-
newColumns.add(expression);
221+
int start = expression.indexOf("(");
222+
int end = expression.lastIndexOf(")");
223+
if (start >= 0 && start < end) {
224+
String[] ks = StringUtil.split(expression.substring(start + 1, end));
225+
226+
String expr = expression.substring(0, start + 1);
227+
for (int j = 0; j < ks.length; j++) {
228+
String ck = ks[j];
229+
boolean hasQuote = false;
230+
if (ck.endsWith("`")) {
231+
String nck = ck.substring(0, ck.length() - 1);
232+
if (nck.lastIndexOf("`") == 0) {
233+
ck = nck.substring(1);
234+
hasQuote = true;
235+
}
236+
}
237+
238+
String rc = null;
239+
if (hasQuote || StringUtil.isName(ck)) {
240+
rc = isEmpty ? null : keyColumnMap.get(ck);
241+
if (rc == null && isEmpty == false && throwWhenNoKey) {
242+
throw new NullPointerException(table + ":{ @column: value } 的 value 中 " + ck + " 不合法!不允许传后端未授权访问的字段名!");
243+
}
244+
}
245+
246+
expr += (j <= 0 ? "" : ",") + (hasQuote ? q : "") + (rc == null ? ck : rc) + (hasQuote ? q : "");
247+
}
248+
249+
newColumns.add(expr + expression.substring(end));
250+
251+
// newColumns.add(expression);
220252
continue;
221253
}
222254

@@ -227,25 +259,42 @@ public static List<String> compatInputColumn(List<String> columns, String table,
227259

228260
if (ck.startsWith("!")) {
229261
if (ck.length() <= 1) {
230-
throw new IllegalArgumentException("@column:value 的 value 中 " + ck + " 不合法! !column 不允许 column 为空字符串!column,!column2,!column3,column4:alias4 中所有 column 必须符合变量名格式!");
262+
throw new IllegalArgumentException("@column:value 的 value 中 " + ck
263+
+ " 不合法! !column 不允许 column 为空字符串!column,!column2,!column3,column4:alias4 中所有 column 必须符合变量名格式!");
231264
}
232265
String c = ck.substring(1);
233266
if (StringUtil.isName(c) == false) {
234-
throw new IllegalArgumentException("@column:value 的 value 中 " + c + " 不合法! column,!column2,!column3,column4:alias4 中所有 column 必须符合变量名格式!");
267+
throw new IllegalArgumentException("@column:value 的 value 中 " + c
268+
+ " 不合法! column,!column2,!column3,column4:alias4 中所有 column 必须符合变量名格式!");
235269
}
236270

237-
String rc = keyColumnMap == null || keyColumnMap.isEmpty() ? null : keyColumnMap.get(c);
271+
String rc = isEmpty ? null : keyColumnMap.get(c);
238272
exceptColumns.add(rc == null ? c : rc); // 不使用数据库别名,以免 JOIN 等复杂查询情况下报错字段不存在 exceptColumnMap.put(nc == null ? c : nc, c); // column:alias
239273
} else {
240-
String rc = keyColumnMap == null || keyColumnMap.isEmpty() ? null : keyColumnMap.get(ck);
274+
boolean hasQuote = false;
275+
if (ck.endsWith("`")) {
276+
String nck = ck.substring(0, ck.length() - 1);
277+
if (nck.lastIndexOf("`") == 0) {
278+
ck = nck.substring(1);
279+
hasQuote = true;
280+
}
281+
}
282+
283+
String rc = null;
284+
if (hasQuote || StringUtil.isName(ck)) {
285+
rc = isEmpty ? null : keyColumnMap.get(ck);
286+
if (rc == null && isEmpty == false && throwWhenNoKey) {
287+
throw new NullPointerException(table + ":{ @column: value } 的 value 中 " + ck + " 不合法!不允许传后端未授权访问的字段名!");
288+
}
289+
}
290+
241291
newColumns.add(rc == null ? ck : rc); // 不使用数据库别名,以免 JOIN 等复杂查询情况下报错字段不存在 newColumns.add(rc == null ? ck : (isQueryMethod ? (rc + ":" + ck) : rc));
242292
}
243293
}
244294
}
245295
}
246296

247-
boolean isEmpty = exceptColumns == null || exceptColumns.isEmpty(); // exceptColumnMap == null || exceptColumnMap.isEmpty();
248-
List<String> allColumns = isEmpty ? null : getClosestValue(VERSIONED_TABLE_COLUMN_MAP, version, table);
297+
List<String> allColumns = exceptColumns == null || exceptColumns.isEmpty() ? null : getClosestValue(VERSIONED_TABLE_COLUMN_MAP, version, table);
249298

250299
if (allColumns != null && allColumns.isEmpty() == false) {
251300

0 commit comments

Comments
 (0)