【问题标题】:How to properly escape user input for the SQL "LIKE" operator? (Postgres)如何正确转义 SQL“LIKE”运算符的用户输入? (Postgres)
【发布时间】:2019-11-17 20:31:43
【问题描述】:

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

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

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

虽然通过预准备语句中的变量传递用户输入,但下划线被 LIKE 运算符解释为通配符,因此上述 SQL 查询匹配用户表中的每个条目。

建议的解决方案

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

这是一个用 TypeScript 编写的用户输入转义的示例实现:

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

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

干杯, derbenoo

【问题讨论】:

    标签: sql postgresql user-input


    【解决方案1】:

    如果您不想使用通配符,请不要使用like。而是:

    where position(? in name) > 0
    

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

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

    【讨论】:

    • 感谢您的回复 Gordon Linoff,我不知道 position 功能。阅读文档,我完全同意您的回答,即我描述的用例最好使用 position 函数而不是 LIKE 运算符来实现。在实现过程中,我注意到 WHERE 子句必须是 WHERE position(? in name) > 0 以便它评估为布尔值。
    • 不错!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 2010-11-28
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多