java – 准备语句如何比语句更好地防止SQL注入?

背景:我已经开始使用JDBC和MYSQL来模拟书店,所有本地项目.为了连接到数据库,我开始使用Statement,但我开始读到,当多次使用查询只更改其参数时,为这些查询使用PreparedStatement会更有效.但是,我最常阅读的优点是Pre...

背景:我已经开始使用JDBC和MYSQL来模拟书店,所有本地项目.为了连接到数据库,我开始使用Statement,但我开始读到,当多次使用查询只更改其参数时,为这些查询使用PreparedStatement会更有效.但是,我最常阅读的优点是PreparedStatements如何更好地防止SQL注入.

资料来源:
这个帖子的答案here
谷歌
教授

我的问题:
在处理参数化查询时,PreparedStatements如何更好地阻止SQL注入,甚至不同于语句?我很困惑,因为如果我理解正确,值仍然会被传递到执行的SQL语句中,这只取决于程序员清理输入.

解决方法:

你是对的,你可以自己做所有的卫生,因此注射安全.但这更容易出错,因此不太安全.换句话说,自己动手会为可能导致注入漏洞的错误带来更多机会.

一个问题是转义规则可能因DB而异.例如,标准SQL只允许使用单引号(‘foo’)中的字符串文字,因此您的卫生设施可能只会逃避那些;但是MySQL允许使用双引号(“foo”)中的字符串文字,如果你不对它们进行消毒,如果你使用MySQL,你将会受到注入攻击.

如果使用PreparedStatement,则该接口的实现由相应的JDBC驱动程序提供,该实现负责转义输入.这意味着清理代码是由编写JDBC驱动程序的人编写的,这些人可能知道数据库特定的转义规则的来龙去脉.他们也很可能比你测试手动转义函数更彻底地测试那些逃避规则.

因此,如果您编写preparedStatement.setString(1,name),该方法的实现(同样,由您正在使用的DB的JDBC驱动程序人员编写)可能大致如下:

public void setString(int idx, String value) {
    String sanitized = ourPrivateSanitizeMethod(value);
    internalSetString(idx, value);
}

(请记住,上面的代码是一个非常粗略的草图;许多JDBC驱动程序实际上处理它的方式完全不同,但原理基本相同.)

另一个问题是myUserInputVar是否已被清理可能是不明显的.请看以下代码段:

private void updateUser(int name, String id) throws SQLException {
    myStat.executeUpdate("UPDATE user SET name=" + name + " WHERE id=" + id);
}

这样安全吗?您不知道,因为代码中没有任何内容表明名称是否已被清理.而且你不能只是重新消毒“保持安全”,因为这会改变输入(例如,你好’世界会变成你好’世界).另一方面,UPDATE用户SET名称的准备语句=? WHERE id =?总是安全的,因为PreparedStatement的实现在将值插入?之前会转义输入.

本文标题为:java – 准备语句如何比语句更好地防止SQL注入?

基础教程推荐