如何向psycopg2生成的SQL查询中传入<、<>、>=等比较运算符?
实现方案
完全可以实现,但要注意禁止直接拼接未校验的用户输入避免SQL注入风险,具体实现逻辑如下:
- 比较运算符属于SQL语法关键字,不能通过
%s值占位符传入,需要借助psycopg2自带的sql模块做安全拼接,同时必须配合白名单校验拦截非法输入。
具体实现步骤
- 首先定义工具支持的所有合法比较运算符白名单,从根源杜绝注入风险,可作为类属性或全局常量定义:
ALLOWED_COMP_OPS = {'<', '>', '<=', '>=', '=', '<>', '!='}
- 修改查询执行逻辑,先校验用户选中的运算符是否在白名单内,校验通过后再通过
sql.SQL对象将运算符插入SQL模板,修改后的comparison分支代码如下:
if self.current_condition == 'comparison': # 校验选中运算符的合法性 selected_op = self.comp_selec.strip() if selected_op not in ALLOWED_COMP_OPS: raise ValueError(f"非法比较运算符: {selected_op}") # SQL模板给运算符预留{op}占位符 comparison_command = '''SELECT * FROM {table} WHERE {pkey} {op} %s''' cur.execute( sql.SQL(comparison_command).format( table=sql.Identifier(self.current_table), pkey=sql.Identifier(self.current_columns[0].text()), op=sql.SQL(selected_op) # 校验通过的运算符用sql.SQL包裹传入 ), (self.comp_value, ) )
注意事项
- 白名单校验是必须环节:不要信任前端传入的参数,即便界面用单选按钮限制了选项,也存在参数被篡改、传入恶意字符串的风险,针对固定集合的运算符做白名单校验是成本最低、最可靠的防护方式。
- 不要用原生字符串格式化直接拼接运算符:比如不要写
f"WHERE {pkey} {selected_op} %s"这类原生拼接逻辑,表名、字段名、运算符这类SQL结构部分,必须统一通过psycopg2的sql模块处理拼接,和你现有代码的安全逻辑保持一致。
内容的提问来源于stack exchange,提问作者Noerigarnhy
相关产品推荐
相关产品推荐

