使用 ? 创建用户并创建角色作为PreparedStatement占位符

问题描述 投票:0回答:1

我正在尝试以允许使用参数的方式从 Java 代码针对 HSQLDB 数据库发出

CREATE USER
语句。

但是,以下行:

connection.prepareStatement("CREATE USER ? PASSWORD ?;");

抛出异常:

java.sql.SQLSyntaxErrorException: unexpected token: ? in statement [CREATE USER ? PASSWORD ?;]
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
    at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
    at (somewhere in my code)

同样的情况发生在

connection.prepareStatement("CREATE ROLE ?;");

当然,我可以在没有

?
的情况下通过将值直接粘贴到语句中来组装字符串,尽管这会带来一些 SQL 注入的可能性。

所以我想知道为什么占位符不起作用。这些陈述是否得到支持?还是我还漏掉了其他东西?

jdbc parameters prepared-statement
1个回答
3
投票

一般情况下,数据库只允许在DML中使用参数,不允许在DDL中使用参数。在 DML 中,仅允许使用values。在

CREATE USER
CREATE ROLE
的情况下,您处理的不是值而是 identifiers (至少不是用户或角色名称),因此参数化对于这些是不可能的。这类似于在 select 语句中不允许使用表名或列名参数。

理论上,

PASSWORD
子句中的密码之类的东西是一个值,可以参数化,但实际上这是不可能的(至少,我不知道),因为所有 DDL 都被处理为非-可参数化。

作为防止 SQL 注入的一种次要形式,自 JDBC 4.3(在 Java 9 中引入)以来,您可以使用

Statement.enquoteIdentifier
来引用标识符,并使用
Statement.enquoteLiteral
来引用密码等文字。这些方法有一个默认实现,但如果您使用的是带有非标准标识符引号的平台(例如 MySQL),那么您必须确保它实际上被覆盖(当前版本的 MySQL Connector/ 中不是这种情况)据我所知)。

© www.soinside.com 2019 - 2024. All rights reserved.