我应该如何清理Java中的数据库输入?
有人可以指点我一个关于安全运行部分来自用户输入的SQL查询的初学者指南吗? 我正在使用Java,但语言中立的指南也很好。
期望的行为是,如果有人在GUI中输入类似的东西
very nice;) DROP TABLE FOO;
数据库应将其视为文字字符串并安全地存储它而不删除任何表。
你肯定想要使用PreparedStatement 。 他们很方便。 这是一个例子 。
使用PreparedStatement而不是Statement
通常,您不应创建连接输入的查询,而应使用PreparedStatement 。
这允许您指定在查询中设置参数的位置,因此Java将负责为您清理所有输入。
PreparedStatement的? 是的,一点没错。 但我认为还有一个步骤:在接近数据库之前validation来自UI的输入和绑定到对象。
我可以看到在PreparedStatement中绑定String的位置可能仍然容易受到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是必要的,但还不够。 在服务器端validation和绑定是关键。
我建议使用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 '"
而不是运行多个查询。