diff --git a/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java b/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java
index 0a44155..6d1ffd0 100644
--- a/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java
+++ b/continew-starter-data/continew-starter-data-core/src/main/java/top/continew/starter/data/core/util/SqlInjectionUtils.java
@@ -16,17 +16,24 @@
package top.continew.starter.data.core.util;
-import java.util.Objects;
+import cn.hutool.core.text.CharSequenceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.regex.Pattern;
/**
* SQL 注入验证工具类
*
- * @author hubin
+ * @author hubin(MyBatis Plus)
+ * @author zhoujf(JeecgBoot)
+ * @author Charles7c
* @since 2.5.2
*/
public class SqlInjectionUtils {
+ private static final Logger log = LoggerFactory.getLogger(SqlInjectionUtils.class);
+
/**
* SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
*/
@@ -39,6 +46,23 @@ public class SqlInjectionUtils {
private static final Pattern SQL_COMMENT_PATTERN = Pattern
.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
+ /**
+ * SQL 语法关键字
+ */
+ private static final String SQL_SYNTAX_KEYWORD = "and |exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|--";
+
+ /**
+ * SQL 函数检查正则
+ */
+ private static final String[] SQL_FUNCTION_PATTERN = new String[] {"chr\\s*\\(", "mid\\s*\\(", " char\\s*\\(",
+ "sleep\\s*\\(", "user\\s*\\(", "show\\s+tables", "user[\\s]*\\([\\s]*\\)", "show\\s+databases",
+ "sleep\\(\\d*\\)", "sleep\\(.*\\)",};
+
+ private static final String MESSAGE_TEMPLATE = "SQL 注入检查: 检查值=>{}<=存在 SQL 注入关键字, 关键字=>{}<=";
+
+ private SqlInjectionUtils() {
+ }
+
/**
* 检查参数是否存在 SQL 注入
*
@@ -46,8 +70,59 @@ public class SqlInjectionUtils {
* @return true:非法;false:合法
*/
public static boolean check(String value) {
- Objects.requireNonNull(value);
- // 处理是否包含 SQL 注释字符 || 检查是否包含 SQ L注入敏感字符
- return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
+ return check(value, null);
+ }
+
+ /**
+ * 检查参数是否存在 SQL 注入
+ *
+ * @param value 检查参数
+ * @param customKeyword 自定义关键字
+ * @return true:非法;false:合法
+ */
+ public static boolean check(String value, String customKeyword) {
+ if (CharSequenceUtil.isBlank(value)) {
+ return false;
+ }
+ // 处理是否包含 SQL 注释字符 || 检查是否包含 SQL 注入敏感字符
+ if (SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find()) {
+ log.warn("SQL 注入检查: 检查值=>{}<=存在 SQL 注释字符或 SQL 注入敏感字符", value);
+ return true;
+ }
+ // 转换成小写再进行比较
+ value = value.toLowerCase().trim();
+ // 检查是否包含 SQL 语法关键字
+ if (checkKeyword(value, SQL_SYNTAX_KEYWORD.split("\\|"))) {
+ return true;
+ }
+ // 检查是否包含自定义关键字
+ if (CharSequenceUtil.isNotBlank(customKeyword) && checkKeyword(value, customKeyword.split("\\|"))) {
+ return true;
+ }
+ // 检查是否包含 SQL 注入敏感字符
+ for (String pattern : SQL_FUNCTION_PATTERN) {
+ if (Pattern.matches(".*" + pattern + ".*", value)) {
+ log.warn(MESSAGE_TEMPLATE, value, pattern);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 检查参数是否存在关键字
+ *
+ * @param value 检查参数
+ * @param keywords 关键字列表
+ * @return true:非法;false:合法
+ */
+ private static boolean checkKeyword(String value, String[] keywords) {
+ for (String keyword : keywords) {
+ if (value.contains(keyword)) {
+ log.warn(MESSAGE_TEMPLATE, value, keyword);
+ return true;
+ }
+ }
+ return false;
}
}
\ No newline at end of file