Bet*_*mos 3 postgresql go sql-like
我想找到文本列以用户给定字符串开头的行,例如,SELECT * FROM users WHERE name LIKE 'rob%'但"rob"是未经验证的用户输入.如果用户写入包含特殊模式字符(如"rob_")的字符串,则它将匹配"robert42"和"rob_the_man".我需要确保字符串字面匹配,我该怎么做?我是否需要在应用程序级别处理转义或者它是一种更美观的方式?
我正在使用PostgreSQL 9.1和go-pgsql for Go.
必须引用_和%字符在LIKE语句中按字面匹配,没有办法解决它.选择是关于客户端或服务器端(通常使用SQL replace(),见下文).另外,为了在一般情况下100%正确,有一些事情需要考虑.
默认情况下,在_或%之前使用的引号字符是反斜杠(\),但可以使用紧跟在LIKE子句之后的ESCAPE子句进行更改.在任何情况下,引号字符必须在模式中重复两次,以便字面上匹配为一个字符.
示例:... WHERE field like 'john^%node1^^node2.uucp@%' ESCAPE '^'将匹配john%node1 ^ node2.uccp @后跟任何内容.
默认选择反斜杠时出现问题:当standard_conforming_strings为OFF 时,它已经用于其他目的(PG 9.1默认情况下它已启用,但之前的版本仍在广泛使用,这是需要考虑的一点).
此外,如果在用户输入注入场景中LIKE通配符的引用是在客户端完成的,那么除了用户输入上已经必需的正常字符串引用之外,它也是如此.
瞥一眼go-pgsql示例告诉它它使用$ N样式的占位符来表示变量...所以这里尝试以某种方式通用的方式编写它:它与standard_conforming_strings一起使用ON或OFF,使用服务器端替换[%_],一个替代引号字符,引用引号字符,并避免sql注入:
db.Query("SELECT * from USERS where name like replace(replace(replace($1,'^','^^'),'%','^%'),'_','^_') ||'%' ESCAPE '^'",
variable_user_input);
Run Code Online (Sandbox Code Playgroud)