带有 SQL 查询问题的准备语句
Prepared Statement with SQL Query issue
下面显示的代码用于搜索工作列表,添加了准备好的语句以防止 SQL 注入,它也很容易受到攻击。查询语句搜索在添加准备好的语句之前起作用,但是现在 returns 什么都没有。谁能看到我做错了什么?谢谢。之前的代码如下所示:
try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/SQL_DB", "root", "root"); Statement stmt = con.createStatement()) {
rs = stmt.executeQuery(queryStatement);
代码现在看起来像这样:
public List<jobs> searchjobs(@RequestParam String query) {
log.debug("REST request to search jobs for query {}", query);
String queryStatement = "SELECT * FROM jobs WHERE description like '%" + query + "%'";
log.info("Final SQL query {}", queryStatement);
ResultSet rs = null;
try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/SQL_DB", "root", "root");
PreparedStatement stmt = con.prepareStatement(queryStatement)) {
stmt.setString(1, query);
rs = stmt.executeQuery(queryStatement);
return extractjobs(rs);
} catch (SQLException ex) {
log.error(ex.getMessage(), ex);
return new ArrayList();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException ex) {
log.error(ex.getMessage(), ex);
}
}
}
您错过了准备好的语句的本质。使用它时,您 将所有变量替换为占位符 像这样
String queryStatement = "SELECT * FROM jobs WHERE description like ?";
然后您可以像以前一样绑定查询变量。只需先添加那些百分比字符即可
stmt.setString(1, "%" + query + "%");
您可能已经阅读了常见的建议"use prepared statements to protect against SQL injection."但是这个建议只说对了一半。
事实是,您应该使用 查询参数 将不受信任的内容与您的查询分开。恰好使用查询参数需要您使用准备好的语句,因此您可以将准备步骤与执行步骤分开,并在这两个步骤之间将参数绑定到准备好的查询。
这有助于防止 SQL 注入,因为准备是在解析您的查询时进行的。如果在解析之前将不受信任的内容与查询分开,那么不受信任的内容就不会引入 SQL 注入。
您的查询没有参数占位符。您像以前一样将不受信任的内容连接到语句中,这意味着它仍然存在 SQL 注入漏洞。
String queryStatement = "SELECT * FROM jobs WHERE description like '%" + query + "%'";
应该是:
String queryStatement = "SELECT * FROM jobs WHERE description like ?";
由于您的查询没有参数占位符,因此当您尝试绑定到它时应该会出错:
stmt.setString(1, query);
这会抛出异常吗?您似乎记录了它,因此请检查您的日志。
下面显示的代码用于搜索工作列表,添加了准备好的语句以防止 SQL 注入,它也很容易受到攻击。查询语句搜索在添加准备好的语句之前起作用,但是现在 returns 什么都没有。谁能看到我做错了什么?谢谢。之前的代码如下所示:
try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/SQL_DB", "root", "root"); Statement stmt = con.createStatement()) {
rs = stmt.executeQuery(queryStatement);
代码现在看起来像这样:
public List<jobs> searchjobs(@RequestParam String query) {
log.debug("REST request to search jobs for query {}", query);
String queryStatement = "SELECT * FROM jobs WHERE description like '%" + query + "%'";
log.info("Final SQL query {}", queryStatement);
ResultSet rs = null;
try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/SQL_DB", "root", "root");
PreparedStatement stmt = con.prepareStatement(queryStatement)) {
stmt.setString(1, query);
rs = stmt.executeQuery(queryStatement);
return extractjobs(rs);
} catch (SQLException ex) {
log.error(ex.getMessage(), ex);
return new ArrayList();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException ex) {
log.error(ex.getMessage(), ex);
}
}
}
您错过了准备好的语句的本质。使用它时,您 将所有变量替换为占位符 像这样
String queryStatement = "SELECT * FROM jobs WHERE description like ?";
然后您可以像以前一样绑定查询变量。只需先添加那些百分比字符即可
stmt.setString(1, "%" + query + "%");
您可能已经阅读了常见的建议"use prepared statements to protect against SQL injection."但是这个建议只说对了一半。
事实是,您应该使用 查询参数 将不受信任的内容与您的查询分开。恰好使用查询参数需要您使用准备好的语句,因此您可以将准备步骤与执行步骤分开,并在这两个步骤之间将参数绑定到准备好的查询。
这有助于防止 SQL 注入,因为准备是在解析您的查询时进行的。如果在解析之前将不受信任的内容与查询分开,那么不受信任的内容就不会引入 SQL 注入。
您的查询没有参数占位符。您像以前一样将不受信任的内容连接到语句中,这意味着它仍然存在 SQL 注入漏洞。
String queryStatement = "SELECT * FROM jobs WHERE description like '%" + query + "%'";
应该是:
String queryStatement = "SELECT * FROM jobs WHERE description like ?";
由于您的查询没有参数占位符,因此当您尝试绑定到它时应该会出错:
stmt.setString(1, query);
这会抛出异常吗?您似乎记录了它,因此请检查您的日志。