fix(pigx-common-data): 添加 SQL 注入检查并移除自定义转义方法

- 在数据权限拦截器中添加 SQL 注入检查,使用 MyBatis-Plus 的 SqlInjectionUtils 工具类
- 移除原有的 escapeSql 自定义转义方法,直接使用原始 username 参数
- 在生成条件表达式和查询语句时增加注入检查逻辑,发现注入风险时返回空结果集
This commit is contained in:
PIGCLOUD committed 2026-03-09 10:46:07 +08:00
1 parent 0198431ffa
commit 61adedf902
1 file changed
+15 -14
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
@@ -128,19 +129,24 @@ public class DataScopeInnerInterceptor implements DataScopeInterceptor {
return CCJSqlParserUtil.parseCondExpression("1 = 2");
}
// SQL 注入检查
if (StrUtil.isNotBlank(username) && SqlInjectionUtils.check(username)) {
return CCJSqlParserUtil.parseCondExpression("1 = 2");
}
// 2. 本人权限 + 部门权限:加括号保证与原有条件组合时的优先级
if (StrUtil.isNotBlank(username) && CollUtil.isNotEmpty(deptIds)) {
String join = CollectionUtil.join(deptIds, ",");
String logicKeyword = dataScope.getLogicMode() != null ? dataScope.getLogicMode().getKeyword()
: DataScopeLogicEnum.OR.getKeyword();
String condSql = String.format("(%s%s = '%s' %s %s%s IN (%s))", prefix, dataScope.getScopeUserName(),
escapeSql(username), logicKeyword, prefix, dataScope.getScopeDeptName(), join);
username, logicKeyword, prefix, dataScope.getScopeDeptName(), join);
return CCJSqlParserUtil.parseCondExpression(condSql);
}
// 3. 仅本人权限
if (StrUtil.isNotBlank(username)) {
String condSql = String.format("%s%s = '%s'", prefix, dataScope.getScopeUserName(), escapeSql(username));
String condSql = String.format("%s%s = '%s'", prefix, dataScope.getScopeUserName(), username);
return CCJSqlParserUtil.parseCondExpression(condSql);
}
@@ -182,6 +188,11 @@ public class DataScopeInnerInterceptor implements DataScopeInterceptor {
return String.format("SELECT %s FROM (%s) temp_data_scope WHERE 1 = 2", selectType, originalSql);
}
// SQL 注入检查
if (StrUtil.isNotBlank(username) && SqlInjectionUtils.check(username)) {
return String.format("SELECT %s FROM (%s) temp_data_scope WHERE 1 = 2", selectType, originalSql);
}
// 本人 + 部门
if (StrUtil.isNotBlank(username) && CollUtil.isNotEmpty(deptIds)) {
String join = CollectionUtil.join(deptIds, ",");
@@ -189,14 +200,14 @@ public class DataScopeInnerInterceptor implements DataScopeInterceptor {
: DataScopeLogicEnum.OR.getKeyword();
return String.format(
"SELECT %s FROM (%s) temp_data_scope WHERE (temp_data_scope.%s = '%s' %s temp_data_scope.%s IN (%s))",
selectType, originalSql, dataScope.getScopeUserName(), escapeSql(username), logicKeyword,
selectType, originalSql, dataScope.getScopeUserName(), username, logicKeyword,
dataScope.getScopeDeptName(), join);
}
// 仅本人
if (StrUtil.isNotBlank(username)) {
return String.format("SELECT %s FROM (%s) temp_data_scope WHERE temp_data_scope.%s = '%s'", selectType,
originalSql, dataScope.getScopeUserName(), escapeSql(username));
originalSql, dataScope.getScopeUserName(), username);
}
// 仅部门
@@ -205,16 +216,6 @@ public class DataScopeInnerInterceptor implements DataScopeInterceptor {
originalSql, dataScope.getScopeDeptName(), join);
}
/**
* 转义 SQL 字符串值中的单引号,防止 SQL 注入
*/
private String escapeSql(String value) {
if (value == null) {
return "";
}
return value.replace("'", "''");
}
/**
* 查找参数是否包括DataScope对象
*