查询中的 TypeORM、反引号与冒号

TypeORM, Backticks vs. Colon in Query

我一直在使用反引号编写查询

const firstUser = await connection
    .getRepository(User)
    .createQueryBuilder("user")
    .where(`user.id = '${id}'`)
    .getOne();

但在 typeorm 文档中,示例是用冒号书写的。

const firstUser = await connection
    .getRepository(User)
    .createQueryBuilder("user")
    .where("user.id = :id", { id: 1 })
    .getOne();

所以我想知道使用反引号和冒号之间是否有任何区别。

如有任何见解,我们将不胜感激。

谢谢。

不要使用字符串插值将值插入 SQL 语句

抱歉大喊大叫,但这很重要。


当你这样做时:

.where(`user.id = '${id}'`)

然后先创建字符串,再传给where()函数。这意味着如果 id123,则它与:

相同
.where(`user.id = '123'`)

这看起来不错。但是如果 id123' OR 1=1--'

呢?

你现在明白了:

.where(`user.id = '123' OR 1=1--'`) // Now returns ALL users!

这叫做 SQL injection,这是一个很大的安全问题。这非常非常糟糕。攻击者可以更改您的查询并访问他们不应该访问的数据,或者更改记录以授予他们自己管理员访问权限,或者其他各种非常糟糕的事情。几乎可以让 每个人 完全 read/write 访问您的数据库。


这让我们想到了:

.where("user.id = :id", { id: 1 })

为了解决这个问题,您要求 TypeORM 为您输入值,这正确地转义了攻击者可能添加的任何值,因此输入没有可执行指令。

如果 id 是邪恶的东西,那么它会变成这样的东西:

.where(`user.id = '123\' OR 1=1--'`) // note the backslash
// (actual query may vary based on different databases)

此处 TypeORM 通过转义攻击者插入的右引号来确保将 id 作为值处理。这使得获取用户提供的值并在您的查询中使用它们变得安全。


总而言之,从不将用户提供的值直接插入到查询中(为了安全起见,实际上应该是所有值),总是 使用查询参数来确保正确缩放值。