我应该如何清理 Java 中的数据库输入?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/687787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:23:34  来源:igfitidea点击:

How should I sanitize database input in Java?

javamysqlsecuritysql-injection

提问by Benjamin Confino

Could someone please point me to a good beginner guide on safely running SQL queries formed partly from user input? I'm using Java, but a language neutral guide is fine too.

有人可以给我指点一个关于安全运行部分由用户输入形成的 SQL 查询的好的初学者指南吗?我正在使用 Java,但是语言中立的指南也很好。

The desired behaviour is that if someone types into the GUI something like

所需的行为是,如果有人在 GUI 中键入类似

very nice;) DROP TABLE FOO;

very nice;) DROP TABLE FOO;

The database should treat it as a literal string and store it safely without dropping any tables.

数据库应将其视为文字字符串并安全地存储它而不删除任何表。

采纳答案by Josh Stodola

You definitely want to use PreparedStatements. They are convenient. Here is an example.

你肯定想使用PreparedStatements。他们很方便。这是一个例子

回答by Geo

回答by Seb

Normally, you shouldn't create a query concatenating input, but using PreparedStatementinstead.

通常,您不应创建连接输入的查询,而应使用PreparedStatement

That lets you specify in which places you'll be setting your parameters inside your query, so Java will take care of sanitizing all inputs for you.

这使您可以指定将在查询中的哪些位置设置参数,因此 Java 将负责为您清理所有输入。

回答by duffymo

PreparedStatement? Yes, absolutely. But I think there's one more step: validation of input from UI and binding to objects prior to getting close to the database.

准备语句?是的,一点没错。但我认为还有一个步骤:在接近数据库之前验证来自 UI 的输入并绑定到对象。

I can see where binding a String in PreparedStatement might still leave you vulnerable to a SQL injection attack:

我可以看到在 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();

I've gotta admit that I haven't tried it myself, but if this is remotely possible I'd say PreparedStatement is necessary but not sufficient. Validating and binding on the server side is key.

我必须承认我自己还没有尝试过,但如果这是远程可能的,我会说 PreparedStatement 是必要的,但还不够。服务器端的验证和绑定是关键。

I'd recommend doing it with Spring's binding API.

我建议使用 Spring 的绑定 API 来完成它。

回答by bgiles

Your user input would actually have to be "Bob'; delete from foo; select '"(or something like that) so the implicit quotes added by the prepared statement would be closed:

您的用户输入实际上必须是"Bob'; delete from foo; select '"(或类似的),因此准备好的语句添加的隐式引号将被关闭:

SELECT * FROM FOO WHERE NAME = 'Bob'; delete from foo; select ''

but if you do that the prepared statement code will quote your quote so you get an actual query of

但是如果你这样做了,准备好的语句代码会引用你的报价,所以你会得到一个实际的查询

SELECT * FROM FOO WHERE NAME = 'Bob''; delete from foo; select '''

and your name would be stored as "Bob', delete from foo; select '"instead of running multiple queries.

并且您的姓名将被存储为"Bob', delete from foo; select '"而不是运行多个查询。