【发布时间】:2009-03-26 22:25:24
【问题描述】:
有人可以指点我一份关于安全运行部分由用户输入形成的 SQL 查询的初学者指南吗?我正在使用 Java,但语言中立的指南也很好。
期望的行为是,如果有人在 GUI 中键入类似
的内容very nice;) DROP TABLE FOO;
数据库应将其视为文字字符串并安全地存储它而不会删除任何表。
【问题讨论】:
标签: java mysql security sql-injection
有人可以指点我一份关于安全运行部分由用户输入形成的 SQL 查询的初学者指南吗?我正在使用 Java,但语言中立的指南也很好。
期望的行为是,如果有人在 GUI 中键入类似
的内容very nice;) DROP TABLE FOO;
数据库应将其视为文字字符串并安全地存储它而不会删除任何表。
【问题讨论】:
标签: java mysql security sql-injection
您肯定想使用PreparedStatements。它们很方便。这是example。
【讨论】:
【讨论】:
通常,您不应该创建连接输入的查询,而是使用PreparedStatement。
这使您可以指定要在查询中的哪些位置设置参数,因此 Java 将负责为您清理所有输入。
【讨论】:
PreparedStatement?是的,一点没错。但我认为还有一步:在接近数据库之前验证来自 UI 的输入并绑定到对象。
我可以看到在 PreparedStatement 中绑定字符串可能仍会使您容易受到 SQL 注入攻击:
String userInput = "Bob; DELETE FROM FOO";
String query = "SELECT * FROM FOO WHERE NAME = ?";
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, userInput);
ps.executeQuery();
我必须承认我自己没有尝试过,但如果这有可能,我会说 PreparedStatement 是必要的,但还不够。在服务器端验证和绑定是关键。
我建议使用 Spring 的绑定 API。
【讨论】:
您的用户输入实际上必须是"Bob'; delete from foo; select '"(或类似的东西),因此准备好的语句添加的隐式引号将被关闭:
SELECT * FROM FOO WHERE NAME = 'Bob'; delete from foo; select ''
但如果你这样做,准备好的语句代码将引用你的报价,以便你得到一个实际的查询
SELECT * FROM FOO WHERE NAME = 'Bob''; delete from foo; select '''
您的姓名将被存储为"Bob', delete from foo; select '",而不是运行多个查询。
【讨论】: