Skip to content

Commit

Permalink
操作方法 Operation 新增 MUST 和 REFUSE 分别替代 NECESSARY 和 DISALLOW;解决 Structur…
Browse files Browse the repository at this point in the history
…e.sqlVerify 不可用及预防可能的 SQL 注入;解决 SQLConfig 自定义的 idKey 和 userIdKey 在 Structure 中未同步导致自定义值校验不通过;
  • Loading branch information
TommyLemon committed Nov 21, 2020
1 parent 9e501d4 commit c32498b
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 58 deletions.
21 changes: 18 additions & 3 deletions APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import apijson.RequestMethod;
import apijson.RequestRole;
import apijson.StringUtil;
import apijson.orm.AbstractSQLConfig.IdCallback;
import apijson.orm.exception.ConditionErrorException;
import apijson.orm.exception.ConflictException;
import apijson.orm.exception.NotExistException;
Expand All @@ -43,7 +44,7 @@
/**parser for parsing request to JSONObject
* @author Lemon
*/
public abstract class AbstractParser<T> implements Parser<T>, ParserCreator<T>, VerifierCreator<T>, SQLCreator {
public abstract class AbstractParser<T> implements Parser<T>, ParserCreator<T>, VerifierCreator<T>, SQLCreator, IdCallback {
protected static final String TAG = "AbstractParser";


Expand Down Expand Up @@ -490,11 +491,25 @@ public JSONObject parseCorrectRequest(RequestMethod method, String tag, int vers

//获取指定的JSON结构 >>>>>>>>>>>>>>


//JSONObject clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {}
return Structure.parseRequest(method, name, target, request, maxUpdateCount, creator);
return Structure.parseRequest(method, name, target, request, maxUpdateCount, getGlobleDatabase(), getGlobleSchema(), this, creator);
}


@Override
public String getIdKey(String database, String schema, String table) {
return apijson.JSONObject.KEY_ID;
}
@Override
public String getUserIdKey(String database, String schema, String table) {
return apijson.JSONObject.KEY_USER_ID;
}
@Override
public Object newId(RequestMethod method, String database, String schema, String table) {
return System.currentTimeMillis();
}


/**新建带状态内容的JSONObject
* @param code
* @param msg
Expand Down
68 changes: 54 additions & 14 deletions APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
import static apijson.JSONObject.KEY_ID;
import static apijson.JSONObject.KEY_JSON;
import static apijson.JSONObject.KEY_ORDER;
import static apijson.JSONObject.KEY_ROLE;
import static apijson.JSONObject.KEY_RAW;
import static apijson.JSONObject.KEY_ROLE;
import static apijson.JSONObject.KEY_SCHEMA;
import static apijson.JSONObject.KEY_USER_ID;
import static apijson.RequestMethod.DELETE;
Expand Down Expand Up @@ -48,20 +48,28 @@
import com.alibaba.fastjson.annotation.JSONField;

import apijson.JSON;
import apijson.JSONResponse;
import apijson.Log;
import apijson.NotNull;
import apijson.RequestMethod;
import apijson.RequestRole;
import apijson.SQL;
import apijson.StringUtil;
import apijson.orm.exception.NotExistException;
import apijson.orm.model.Access;
import apijson.orm.model.Column;
import apijson.orm.model.Document;
import apijson.orm.model.ExtendedProperty;
import apijson.orm.model.Function;
import apijson.orm.model.PgAttribute;
import apijson.orm.model.PgClass;
import apijson.orm.model.Request;
import apijson.orm.model.Response;
import apijson.orm.model.SysColumn;
import apijson.orm.model.SysTable;
import apijson.orm.model.Table;
import apijson.orm.model.Test;
import apijson.orm.model.TestRecord;

/**config sql for JSON Request
* @author Lemon
Expand All @@ -77,6 +85,7 @@ public abstract class AbstractSQLConfig implements SQLConfig {
* 表名映射,隐藏真实表名,对安全要求很高的表可以这么做
*/
public static final Map<String, String> TABLE_KEY_MAP;
public static final List<String> CONFIG_TABLE_LIST;
public static final List<String> DATABASE_LIST;
// 自定义where条件拼接
public static final Map<String, String> RAW_MAP;
Expand All @@ -89,6 +98,16 @@ public abstract class AbstractSQLConfig implements SQLConfig {
TABLE_KEY_MAP.put(SysTable.class.getSimpleName(), SysTable.TABLE_NAME);
TABLE_KEY_MAP.put(SysColumn.class.getSimpleName(), SysColumn.TABLE_NAME);
TABLE_KEY_MAP.put(ExtendedProperty.class.getSimpleName(), ExtendedProperty.TABLE_NAME);

CONFIG_TABLE_LIST = new ArrayList<>(); // Table, Column 等是系统表 AbstractVerifier.SYSTEM_ACCESS_MAP.keySet());
CONFIG_TABLE_LIST.add(Function.class.getSimpleName());
CONFIG_TABLE_LIST.add(Request.class.getSimpleName());
CONFIG_TABLE_LIST.add(Response.class.getSimpleName());
CONFIG_TABLE_LIST.add(Test.class.getSimpleName());
CONFIG_TABLE_LIST.add(Access.class.getSimpleName());
CONFIG_TABLE_LIST.add(Document.class.getSimpleName());
CONFIG_TABLE_LIST.add(TestRecord.class.getSimpleName());


DATABASE_LIST = new ArrayList<>();
DATABASE_LIST.add(DATABASE_MYSQL);
Expand Down Expand Up @@ -1623,8 +1642,18 @@ public String getCompareString(String key, Object value, String type) throws Exc
}

public String getKey(String key) {
if (isTest()) {
if (key.contains("'")) { // || key.contains("#") || key.contains("--")) {
throw new IllegalArgumentException("参数 " + key + " 不合法!key 中不允许有单引号 ' !");
}
return getSQLValue(key).toString();
}

return getSQLKey(key);
}
public String getSQLKey(String key) {
String q = getQuote();
return (isKeyPrefix() ? getAliasWithQuote() + "." : "") + q + key + q;
return (isKeyPrefix() ? getAliasWithQuote() + "." : "") + q + key + q;
}

/**
Expand All @@ -1636,6 +1665,9 @@ private Object getValue(@NotNull Object value) {
preparedValueList.add(value);
return "?";
}
return getSQLValue(value);
}
public Object getSQLValue(@NotNull Object value) {
// return (value instanceof Number || value instanceof Boolean) && DATABASE_POSTGRESQL.equals(getDatabase()) ? value : "'" + value + "'";
return (value instanceof Number || value instanceof Boolean) ? value : "'" + value + "'"; //MySQL 隐式转换用不了索引
}
Expand Down Expand Up @@ -2230,9 +2262,15 @@ public static String getSQL(AbstractSQLConfig config) throws Exception {
case DELETE:
return "DELETE FROM " + tablePath + config.getWhereString(true);
default:
String explain = (config.isExplain() ? (config.isSQLServer() || config.isOracle() ? "SET STATISTICS PROFILE ON " : "EXPLAIN ") : "");
if (config.isTest() && RequestMethod.isGetMethod(config.getMethod(), true)) {
String q = config.getQuote(); // 生成 SELECT ( (24 >=0 AND 24 <3) ) AS `code` LIMIT 1 OFFSET 0
return explain + "SELECT " + config.getWhereString(false) + " AS " + q + JSONResponse.KEY_CODE + q + config.getLimitString();
}

config.setPreparedValueList(new ArrayList<Object>());
String column = config.getColumnString();
return (config.isExplain() ? (config.isSQLServer() || config.isOracle() ? "SET STATISTICS PROFILE ON " : "EXPLAIN ") : "") + "SELECT " + (config.getCache() == JSONRequest.CACHE_RAM ? "SQL_NO_CACHE " : "") + column + " FROM " + getConditionString(column, tablePath, config);
return explain + "SELECT " + (config.getCache() == JSONRequest.CACHE_RAM ? "SQL_NO_CACHE " : "") + column + " FROM " + getConditionString(column, tablePath, config);
}
}

Expand Down Expand Up @@ -2915,16 +2953,7 @@ else if (key.endsWith("-")) {//缩减,PUT查询时处理
}


public static interface Callback {
/**获取 SQLConfig 的实例
* @param method
* @param database
* @param schema
* @param table
* @return
*/
SQLConfig getSQLConfig(RequestMethod method, String database, String schema, String table);

public static interface IdCallback {
/**为 post 请求新建 id, 只能是 Long 或 String
* @param method
* @param database
Expand All @@ -2949,7 +2978,18 @@ public static interface Callback {
* @return
*/
String getUserIdKey(String database, String schema, String table);

}

public static interface Callback extends IdCallback {
/**获取 SQLConfig 的实例
* @param method
* @param database
* @param schema
* @param table
* @return
*/
SQLConfig getSQLConfig(RequestMethod method, String database, String schema, String table);

/**combine 里的 key 在 request 中 value 为 null 或不存在,即 request 中缺少用来作为 combine 条件的 key: value
* @param combine
* @param key
Expand Down
21 changes: 13 additions & 8 deletions APIJSONORM/src/main/java/apijson/orm/Operation.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,26 @@
* @author Lemon
*/
public enum Operation {
/**
* 必须传的字段,结构是
* "key0,key1,key2..."
*/
MUST,
/**
* @deprecated 用 MUST 代替,最早可能 4.5.0 移除
*/
NECESSARY,

/**
* 不允许传的字段,结构是
* "key0,key1,key2..."
* TODO 改成 MUST 减少长度 ?
*/
DISALLOW,

REFUSE,
/**
* 必须传的字段,结构是
* "key0,key1,key2..."
* TODO 改成 REFUSE 减少长度 ?
* @deprecated 用 REFUSE 代替,最早可能 4.5.0 移除
*/
NECESSARY,
DISALLOW,


/**TODO 是否应该把数组类型写成 BOOLEANS, NUMBERS 等复数单词,以便抽取 enum ?扩展用 VERIFY 或 INSERT/UPDATE 远程函数等
* 验证是否符合预设的类型:
Expand Down
Loading

0 comments on commit c32498b

Please sign in to comment.