如何检测Web应用中的SQL注入尝试(Java后端场景)
检测SQL注入尝试并记录日志的Java实现方案
核心思路:别依赖单一正则,结合多维度特征降低误报
单纯靠正则匹配很容易误判(比如用户正常输入含select的内容)或漏判,建议结合SQL注入的常见特征做分层检测,既覆盖多数攻击场景,又减少无效告警。
1. 关键字+特殊字符的组合检测
针对注入攻击常用的“关键字+特殊符号”组合做匹配,比单独检测关键字准确得多:
import java.util.regex.Pattern; public class SqlInjectionDetector { // 匹配常见注入特征,可根据业务调整规则 private static final Pattern SQL_INJECTION_PATTERN = Pattern.compile( "(?i)(union\\s+select|select\\s+.+from|insert\\s+into|drop\\s+(table|database)|or\\s+1\\s*=\\s*1|'\\s*or\\s*'1'='1|--|/\\*.*\\*/)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL ); public static boolean isSuspiciousInput(String input) { if (input == null || input.trim().isEmpty()) { return false; } // 同时满足“含可疑特殊字符”+“匹配注入特征”才标记 boolean hasRiskChars = input.matches(".*['\";\\-/*].*"); boolean hasRiskPattern = SQL_INJECTION_PATTERN.matcher(input).find(); return hasRiskChars && hasRiskPattern; } }
2. 针对性检测注入逻辑特征
单独提取注入攻击常用的逻辑绕开、语句截断特征:
public static boolean hasInjectionLogic(String input) { String lowerInput = input.toLowerCase(); return lowerInput.contains("or 1=1") || lowerInput.contains("and 0=0") || lowerInput.contains("--") || lowerInput.contains("/*"); }
3. 结合业务做白名单校验
如果你的搜索字段有明确输入范围(比如只允许字母、数字、中文),直接用白名单过滤,不在范围内的直接标记可疑:
public static boolean isInvalidInput(String input) { // 示例:仅允许字母、数字、中文和常见标点 return !input.matches("[a-zA-Z0-9\\u4e00-\\u9fa5,.?!\\s]+"); }
4. 日志记录的实用姿势
检测到可疑输入时,记录关键信息方便后续排查:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SecurityLogger { private static final Logger SECURITY_LOG = LoggerFactory.getLogger("security"); public static void logSqlInjectionAttempt(String input, String ip, String requestUri) { SECURITY_LOG.warn("疑似SQL注入尝试 | 输入内容: {} | 请求IP: {} | 请求路径: {}", input, ip, requestUri); } }
避坑提醒
- 别用过于宽泛的正则(比如直接匹配
SELECT),会把正常输入误判为攻击 - 检测只是辅助日志,预编译语句(PreparedStatement)才是核心防护手段,不能本末倒置
- 定期更新检测规则,针对新出现的注入手段调整特征
内容的提问来源于stack exchange,提问作者Tristate
相关产品推荐
相关产品推荐

