JeecgBoot SQL防注入:自定义过滤器与参数校验
引言:企业级应用的安全基石
在当今数字化时代,Web应用安全已成为企业级开发不可忽视的核心问题。SQL注入(SQL Injection)作为OWASP Top 10安全风险榜单的常客,一直是Web应用最致命的安全漏洞之一。JeecgBoot作为企业级低代码开发平台,通过多层次、多维度的安全防护机制,为开发者提供了全面的SQL注入防护解决方案。
本文将深入解析JeecgBoot在SQL防注入方面的核心实现,涵盖自定义过滤器设计、参数校验机制、白名单策略以及最佳实践指南。
SQL注入风险全景图
在深入技术细节前,我们先通过一个流程图了解SQL注入的完整攻击链和防护策略:
核心防护机制解析
1. SqlInjectionUtil:注入检测核心工具类
JeecgBoot通过SqlInjectionUtil类提供了全面的SQL注入检测能力,其主要功能包括:
关键词黑名单检测
// 默认SQL注入关键词黑名单
private final static String XSS_STR = "and |exec |peformance_schema|information_schema|extractvalue|...";
// 正则表达式模式检测
private final static String[] XSS_REGULAR_STR_ARRAY = new String[]{
"chr\\s*\\(", "mid\\s*\\(", "sleep\\s*\\(", "show\\s+tables", "sleep\\(\\d*\\)"
};
表名和字段名校验
// 表名合法性校验正则
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_\\$]{0,63}$");
// 字段名校验正则
static final Pattern fieldPattern = Pattern.compile("^[a-zA-Z0-9_]+$");
public static String getSqlInjectTableName(String table) {
// 校验表名格式合法性
boolean isValidTableName = tableNamePattern.matcher(table).matches();
if (!isValidTableName) {
throw new JeecgSqlInjectionException("表名不合法,存在SQL注入风险!--->" + table);
}
// 进一步关键词检测
filterContentMulti(table);
return table;
}
2. 字典表白名单机制
JeecgBoot实现了基于白名单的字典查询安全机制,通过DictTableWhiteListHandlerImpl类实现:
白名单配置结构
/**
* key-表名
* value-字段名,多个逗号隔开
* 配置示例:
* whiteTablesRuleMap.put("sys_user", "*") // 所有字段允许查询
* whiteTablesRuleMap.put("sys_user", "username,password") // 指定字段允许查询
*/
private static final Map<String, String> whiteTablesRuleMap = new HashMap<>();
白名单校验流程
3. 多层次拦截器架构
JeecgBoot通过拦截器模式实现了请求层面的安全防护:
安全配置类结构
@Component("jeecgBaseConfig")
@ConfigurationProperties(prefix = "jeecg")
public class JeecgBaseConfig {
/**
* 平台安全模式配置
*/
private Firewall firewall;
// ... 其他配置
}
public class Firewall {
/**
* 数据源安全模式
*/
private Boolean dataSourceSafe;
/**
* 低代码模式:dev-开发模式,prod-生产模式
*/
private String lowCodeMode;
// ... 其他安全配置
}
开发模式与生产模式差异
| 模式 | 白名单校验 | 自动添加 | 错误处理 | 适用场景 |
|---|---|---|---|---|
| 开发模式(dev) | 宽松校验 | 支持自动添加 | 记录日志 | 开发测试环境 |
| 生产模式(prod) | 严格校验 | 禁止自动添加 | 直接拒绝 | 线上生产环境 |
实战:自定义安全过滤器
1. 创建自定义SQL注入过滤器
@Component
public class CustomSqlInjectionFilter implements Filter {
private static final List<String> SENSITIVE_PARAMS = Arrays.asList(
"query", "filter", "sort", "order", "search"
);
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
Map<String, String[]> parameterMap = httpRequest.getParameterMap();
// 检查所有请求参数
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String paramName = entry.getKey();
String[] paramValues = entry.getValue();
// 只检查敏感参数
if (isSensitiveParameter(paramName) && paramValues != null) {
for (String value : paramValues) {
if (SqlInjectionUtil.isSqlInjection(value)) {
// 记录安全日志
log.warn("SQL注入攻击检测: IP={}, Param={}, Value={}",
httpRequest.getRemoteAddr(), paramName, value);
// 返回错误响应
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
httpResponse.getWriter().write("检测到非法输入");
return;
}
}
}
}
chain.doFilter(request, response);
}
private boolean isSensitiveParameter(String paramName) {
return SENSITIVE_PARAMS.stream()
.anyMatch(paramName::contains);
}
}
2. 配置过滤器注册
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<CustomSqlInjectionFilter> sqlInjectionFilter() {
FilterRegistrationBean<CustomSqlInjectionFilter> registration =
new FilterRegistrationBean<>();
registration.setFilter(new CustomSqlInjectionFilter());
registration.addUrlPatterns("/*");
registration.setName("customSqlInjectionFilter");
registration.setOrder(1); // 高优先级
return registration;
}
}
参数校验最佳实践
1. 控制器层参数校验
@RestController
@RequestMapping("/api/data")
public class DataController {
@GetMapping("/query")
public ResponseEntity<?> queryData(
@RequestParam @ValidTableName String tableName,
@RequestParam @ValidFieldName String fieldName,
@RequestParam(required = false) String filter) {
// 1. 基础参数校验
tableName = SqlInjectionUtil.getSqlInjectTableName(tableName);
fieldName = SqlInjectionUtil.getSqlInjectField(fieldName);
// 2. 复杂条件过滤
if (StringUtils.isNotBlank(filter)) {
SqlInjectionUtil.specialFilterContentForDictSql(filter);
}
// 3. 执行安全查询
List<?> result = dataService.safeQuery(tableName, fieldName, filter);
return ResponseEntity.ok(result);
}
}
2. 自定义校验注解
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidTableNameValidator.class)
public @interface ValidTableName {
String message() default "表名格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class ValidTableNameValidator implements ConstraintValidator<ValidTableName, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (StringUtils.isBlank(value)) {
return false;
}
try {
SqlInjectionUtil.getSqlInjectTableName(value);
return true;
} catch (JeecgSqlInjectionException e) {
return false;
}
}
}
安全配置指南
1. 应用配置(application.yml)
jeecg:
firewall:
dataSourceSafe: true # 开启数据源安全模式
lowCodeMode: prod # 生产环境使用prod模式
# 自定义白名单配置
white-list:
tables:
sys_user: id,username,realname,phone,email
sys_role: id,role_name,role_code
sys_department: id,depart_name,org_code
2. 数据库白名单管理
JeecgBoot提供了可视化的白名单管理界面,支持:
- 📋 表级权限控制
- 🎯 字段级细粒度权限
- 🔄 动态配置热更新
- 📊 操作审计日志
监控与告警体系
1. 安全日志配置
@Aspect
@Component
@Slf4j
public class SecurityLogAspect {
@AfterThrowing(pointcut = "execution(* org.jeecg..*.*(..))",
throwing = "ex")
public void logSecurityException(JeecgSqlInjectionException ex) {
// 记录详细的安全异常信息
log.warn("SQL注入拦截: {}", ex.getMessage());
// 发送告警通知
securityAlertService.sendAlert("SQL注入攻击尝试", ex.getMessage());
}
}
2. 监控指标收集
@Component
public class SecurityMetrics {
private final MeterRegistry meterRegistry;
private final Counter sqlInjectionAttempts;
public SecurityMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.sqlInjectionAttempts = meterRegistry.counter("security.sql.injection.attempts");
}
public void recordInjectionAttempt(String type, String value) {
sqlInjectionAttempts.increment();
meterRegistry.counter("security.sql.injection.attempts", "type", type).increment();
// 记录详细上下文信息
Tags tags = Tags.of(
"value", StringUtils.abbreviate(value, 50),
"timestamp", Instant.now().toString()
);
meterRegistry.counter("security.sql.injection.details", tags).increment();
}
}
总结与展望
JeecgBoot通过多层次、多维度的SQL注入防护机制,为企业级应用提供了坚实的安全基础:
🛡️ 核心防护能力
- 词法分析:基于黑名单的关键词检测
- 语法校验:表名、字段名格式验证
- 白名单控制:细粒度的数据访问权限
- 运行时防护:请求拦截和参数过滤
🚀 最佳实践建议
- 生产环境务必开启
lowCodeMode: prod模式 - 定期审计白名单配置,确保最小权限原则
- 启用监控,实时发现和响应安全事件
- 代码审查,避免动态SQL拼接
🔮 未来演进方向
随着攻击技术的不断演进,JeecgBoot安全体系也在持续优化:
- AI驱动的异常检测
- 行为分析模型集成
- 零信任架构支持
- 云原生安全适配
通过本文的深入解析,相信您已经对JeecgBoot的SQL注入防护机制有了全面了解。在实际项目中,请结合业务场景合理配置安全策略,构建更加安全可靠的企业级应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



