如何正确转义 SQL“LIKE”运算符的用户输入?(Postgres)

Der*_*Ben 5 sql postgresql user-input

LIKE具有用户提供的输入的运算符

Postgres LIKE运算符对于向用户提供对表行的基本搜索非常有用。但是,用户为运算符提供的输入需要正确转义,因为正在解释LIKE某些字符(例如下划线 ( ))。_始终建议通过 Postgres准备好的语句传递用户提供的输入:

PREPARE getUsernames(text) AS
SELECT "name" FROM "users" WHERE "name" LIKE '%' || $1 || '%';
EXECUTE getUsernames('_')
Run Code Online (Sandbox Code Playgroud)

尽管通过预准备语句中的变量传递用户输入,但下划线会被LIKE运算符解释为通配符,以便上述 SQL 查询与 users 表中的每个条目相匹配。

建议的解决方案

用户期望搜索下划线返回包含name下划线字符的所有结果(而不是将其解释为通配符)。因此,我们必须转义用户输入,使其永远不会被LIKE操作员解释。Postgres 提供了转义字符的规范,默认情况下是反斜杠。所以每一个具有特殊含义的字符都必须使用这个转义字符进行转义。然而,保留字符黑名单感觉很容易出错,因为黑名单总是有可能不完整。因此,我提出的解决方案的想法是始终在用户输入的每个字符前面加上转义字符,无论它是否实际上会被解释。Postgres 接受这种不需要转义的字符转义。

以下是用 TypeScript 编写的用户输入转义的示例实现:

function escapePostgresLikeStr(str: string, escapeChar = '\\'): string {
  return str
    .split('')
    .map(char => `${escapeChar}${char}`)
    .join('');
}

Run Code Online (Sandbox Code Playgroud)

我没有找到有关此特定问题的任何信息,因此欢迎任何反馈、安​​全考虑和改进!:)

干杯,德贝努

Gor*_*off 6

如果您不希望使用通配符,请不要使用like。反而:

where position(? in name) > 0
Run Code Online (Sandbox Code Playgroud)

请注意,这?是一个参数占位符,因此您不必使用(危险的)用户输入来处理查询字符串。

LIKE如果您希望用户利用通配符,请使用(或更好的正则表达式)。否则,我看不出这样做有什么好处。