java - 如何在java中用整数类型替换字符串中的字符串?
问题描述
我有一个要求。技术太老了,根本不支持spring。它是带有 jdbc 连接的纯 java 应用程序。
要求是:假设
select * from employee where empid = <<empid>> and designation = 'Doctor'
我正在尝试用 java 中的实际 int 值替换 <> 。我该怎么做?
String query = "select * from employee where empid = <<empid>> and designation = 'Doctor'";
if(query.contains("<<empid>>"))
/// Here I want to replace <<empid>> with actual int value in java
任何线索都会有所帮助
解决方案
您未粘贴的实际执行 SQL 的代码是 [A] 需要认真重写的大规模安全漏洞,或者 [B] 正在使用PreparedStatement
.
这就是问题所在:SQL 注入。通过将模板或一堆字符串常量与一堆用户输入混合来创建 SQL 字符串是一种安全漏洞。例如,如果您尝试SELECT * FROM users WHERE email = 'foo@bar.com'
通过 eg进行制作String sql = "SELECT * FROM users WHERE email = '" + email + "'";
,问题是,如果用户在网络表单中的“电子邮件”字段中输入:whatever@foo.com'; DROP TABLE users CASCADE; EXEC 'FORMAT C: /y /force'; --
?那么SQL就变成了:
SELECT * FROM users WHERE email = 'whatever@foo.com'; DROP TABLE users CASCADE; EXEC 'FORMAT C: /y /force'; --';
那是合法的 SQL,你真的,真的,真的不希望你的数据库引擎执行它。
每个数据库引擎对什么是真正的合法都有自己的想法,并且可能会做一些疯狂的事情,例如将大引号视为真正的引号等。因此,没有您能想到的可行的黑名单或白名单技术可以适当地涵盖所有基础:您需要让您的数据库引擎为您执行此操作,您无法自己修复此漏洞。
Java 通过java.sql.PreparedStatement
. 相反,您总是将一个完全恒定的 SQL 字符串传递给引擎,然后填写空白,可以这么说:
PreparedStatement ps = con.prepareStatement("SELECT * FROM users WHERE email = ?");
ps.setString(1, "foo@whatever.com");
ps.query();
这就是你的做法(并添加try-with-resources,就像你应该已经在这里做的那样;语句和结果集是你必须始终关闭的资源)。即使您调用.setString(1, "foo@whatever.com'; DROP TABLE users CASCADE; --")
,它也会简单地在数据库中查找该字段中包含该email
字段的行。它不会删除整个用户表。消除了安全漏洞(这是消除它的唯一可行方法)。
因此,请查看该代码。是否使用preparedstatement?在这种情况下,代码需要调用的一种或另一种方式:
ps.setInt(1, 999);
Where ps
isPreparedStatement
创建的对象connection.prepareStatement(...)
where...
是 SQL 常量,或者至少是您的输入字符串,其中<<empid>>
被问号替换,并且从不使用来自不受信任来源的任何字符串输入。1
inps.setInt(1, 999)
是问号的位置(1 = 第一个问题变成 999),而 the是999
你的实际数字。它可能看起来像:
if (input instanceof String) {
ps.setString(idx++, (String) input);
} else if (input instanceof Integer) {
ps.setInt(idx++, ((Integer) input).intValue());
} ...
等等。如果您没有看到,请找到setInt
调用并弄清楚如何到达那里。如果您没有看到任何setInt
,那么如果不对此代码进行一些更新,就不可能实现您想要的。
如果您甚至没有看到PreparedStatement
代码中的任何地方,天哪!立即使该服务器脱机,研究是否发生了安全漏洞,如果该服务器存储了欧洲数据,您有 72 小时的时间通知所有用户它是否存在,或者您无法合理地确定,例如通过检查它没有的日志,或者您违反了 GDPR。然后重写该部分使用PreparedStatement
以解决问题。
推荐阅读
- matlab - cvpartition 和 crossvalind 有什么区别
- php - Laravel 5.6将电子邮件字段名称更改为忘记密码的用户名
- python - DataFlow 使用 Airflow DataflowHook.start_python_dataflow 失败并返回代码 1
- python - 分布的迭代排列
- r - 在 pmin 中使用 na.rm=T 和 do.call
- php - 如何获取没有完整路径名的目录树迭代器的目录
- kotlin - Kotlin - 获取可空泛型类型推断的不可空推断
- nfc - Android Wear 上的 NFC 阅读器模式
- ruby-on-rails - 我正在尝试在数字海洋中部署,当最后一部分到达 ActiveSupport::MessageEncryptor::InvalidMessage
- javascript - onunload 如何影响页面性能