encodeForSQL() 不存在于 ESAPI,其 Encoder 仅支持 HTML/JS 等输出编码,不适用于 SQL;防 SQL 注入必须用 Validator 白名单校验 + PreparedStatement 参数化查询双重防护。
ESAPI 本身不提供 SQL
编码
器(
)来“过滤”SQL 输入——这是常见误解。它没有
这类方法,强行用
或
处理 SQL 参数,不仅无效,还会破坏数据语义(比如把单引号转成
,导致查询永远不匹配)。真正防 SQL 注入,靠的是验证 + 预编译,不是编码。
为什么不能用 ESAPI 的 Encoder 防 SQL 注入
ESAPI 的
接口设计目标是**上下文感知的输出编码**,例如防止 XSS 时对 HTML、JS、CSS、URL 等不同输出场景做转义。SQL 查询不是它的编码目标场景:
在 ESAPI 2.x 和 3.x 中均
不存在
试图用
处理数据库参数,会导致存储或查询时多出 HTML 实体,查不到原数据
即使手动替换单引号、分号等字符,也容易漏掉注释符(
、
)、空字节、宽字节绕过等变种
ESAPI 的
才是处理输入安全的正确入口,且必须配合白名单逻辑
该用 ESAPI.Validator 做输入校验,而不是 Encoder
ESAPI 提供
和
等方法,本质是白名单驱动的输入净化。它不会“模糊清洗”,而是严格比对
中定义的正则规则:
校验用户名(只允许字母数字下划线):
校验 ID 必须为正整数:
关键点:
是
里定义的规则名,必须提前配置,例如:
第 5 个参数
表示“不接受空值”;第 6 个
表示“不记录日志异常”——生产环境建议设为
以便审计
ESAPI Validator 必须搭配 PreparedStatement 才有效
仅靠
校验不能替代参数化查询。它只是第一道防线,防止非法格式数据进入业务流程;而 PreparedStatement 才是阻断注入的最终执行层:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
错误组合(校验了但还是拼接):
正确组合(校验 + 预编译):
如果校验失败,
默认抛
,需捕获并拒绝请求,不能静默 fallback
注意:Validator 对模糊匹配(如 LIKE 查询中的
)支持有限,这类场景必须改用
占位符 + 后端逻辑控制通配符位置
validation.properties 规则配置容易被忽略的细节
ESAPI 启动时会加载
,但很多项目只复制了模板,没改规则或路径不对,导致
实际走默认宽松策略:
文件必须放在
根路径,或通过系统属性指定:
规则名区分大小写,且必须与代码中
的第一个参数完全一致
正则表达式不要加
包裹(Java Properties 不支持),直接写
ESAPI 2.5.3.1 默认不启用
(规范化),若需处理 Unicode 归一化或路径遍历,得显式调用
等专用方法
真正起作用的从来不是“把输入塞进某个 encode 方法”,而是明确知道哪个环节该做什么:Validator 负责格式准入,PreparedStatement 负责执行隔离,缺一不可。配置错一个路径、漏写一个规则名、或把校验结果又拿去拼 SQL——前面所有动作都归零。
EncoderencodeForSQL()encoder.encodeForHTML()encodeForJavaScript()'Encoderencoder.encodeForSQL()encodeForHTML()--/*ValidatorValidator.getValidInput()getValidInteger()validation.propertiesString safeName = validator.getValidInput("username", userInput, "UserIdentifier", 20, false, false);int safeId = validator.getValidInteger("userId", userInput, 1, Integer.MAX_VALUE, false);"UserIdentifier"validation.propertiesUserIdentifier=^[a-zA-Z0-9_]{3,20}$falsefalsetrueValidatorString safeName = validator.getValidInput(...);
String sql = "SELECT * FROM users WHERE name = '" + safeName + "'"; // 仍危险!String safeName = validator.getValidInput(...);
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, safeName); // 此处传入已校验值,双重保险getValidInput()ValidationException%PreparedStatementvalidation.propertiesValidatorclasspath:-Desapi.resources.directory=src/main/resources/esapigetValidInput("xxx", ...)/^[0-9]{4,6}$canonicalizevalidator.getValidDirectoryPath()