JDBI - JDBI 中@define 和@bind 有什么区别?

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

这两个函数都经过清理/安全,可以防止 SQL 注入吗?例如,请考虑以下情况:

@SqlUpdate("INSERT INTO <tableName> (<columns>) VALUES (<values>)")
    public abstract void addRowToDataset(@Define("tableName") String tableName, @Define("columns") String columns, @BindIn("values") Collection<Object> values);

我目前的理解是,

@define
字面上将字符串按原样插入到查询中,但
@bind
进行清理。因此,如果我们控制
columns
和 tableName
parameters
并且只有
values
参数是用户输入,那么我们应该没问题。

java sql jdbi
3个回答
14
投票

我遇到了同样的问题,发现答案出奇地难以找到。一位同事告诉我,这只是上一代编程人员的常识,所以随着软件的发展,它的文档可能被遗忘了。

事实上,Oracle的绑定和定义乍一看似乎很有希望,但完全具有误导性,因为它的“定义”是指设置检索结果的引用,这与JDBI中的含义完全不同。

如果我的同事是正确的,这就是他们的实际含义:

  • @Define
    用于常量,并插值格式
    <field>
  • @Bind
    用于变量,并插入格式
    :field
    (“命名参数”)。你是对的:绑定的副作用是发生清理。
  • @BindIn
    用于列表,并插入格式
    (element IN (<field>))
    。这些元素也经过消毒。

我的错误是对

<field>
参数使用
@Bind
格式,这导致插值始终为空字符串。


0
投票

在最受好评的答案之上。根据我的测试和解释,我只想补充一点:

  • @Bind 主要用于查询和更新/创建数据的地方。每个示例在
    WHERE
    VALUES(...)
  • 之后
  • @Define 主要用于 SQL 语句的其他部分,例如带有条件的地方或每个示例的 ORDER BY 中:
@SqlQuery("SELECT * FROM $table ORDER BY <orderByWinsOrPlays>") 
fun getPlayerRankings(@Define orderByWinsOrPlays: String)

<orderByWinsOrPlays>
替换为
:orderByWinsOrPlays
并将
@Define
替换为
@Bind("orderByWinsOrPlays")
不起作用,但不会引发错误。反复测试这两个选项使我得出这个结论。并且用@Define注释的类型参数最好应该是一个原始对象,否则不起作用。对于复杂的对象,使用@BindBean


0
投票

@Bind
用于 JDBC 准备语句 的参数。在 JDBI 中,参数在字符串中表示为
:var
。参数仅出现在查询的某些部分,通常作为
WHERE
子句的一部分,例如
SELECT * FROM Foo WHERE bar = :bar
,或在
VALUES()
INSERT
中。例如,它们通常不能用于指定要从中选择的表。由于 JDBI 在处理参数时在幕后使用
PreparedStatement
,因此可以缓解 SQL 注入。

@Define

 用于 
JDBI 字符串模板中的属性。在 JDBI 中,它们在字符串中表示为 <var>
。它们可以出现在 SQL 中的任何位置,甚至出现在预准备语句不支持的位置,例如
SELECT name FROM <table>

@Define

 似乎是为了动态构建查询,但考虑到意外 SQL 注入的风险,应该谨慎使用。

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