如何用psycopg2的sql.SQL与sql.Literal避免IN子句SQL注入?
解决方法
直接用字符串拼接SQL语句不仅会导致单引号处理错误,还存在严重的SQL注入风险。用psycopg2.sql模块的SQL和Literal可以安全处理这类场景,具体实现如下:
正确代码示例
from psycopg2 import sql # 获取用户传入的国家数组 countries = query["countries"] # 处理空数组的边界情况(避免IN()语法错误) if not countries: # 返回空结果集 cursor.execute("SELECT * FROM contact WHERE 1=0;") else: # 构造安全的SQL查询 query = sql.SQL("SELECT * FROM contact WHERE country IN ({})").format( sql.SQL(",").join(map(sql.Literal, countries)) ) cursor.execute(query)
关键逻辑说明
sql.SQL():用于定义静态的SQL模板部分,确保这部分内容不会被当成用户输入解析,从根源避免注入风险。sql.Literal():将每个用户传入的国家名称转换为安全的SQL字面量,自动处理单引号转义(比如把O'Neil转成'O''Neil'),解决单引号导致的语法错误。sql.SQL(",").join(...):把多个Literal对象用逗号连接,生成合法的IN子句参数列表。
原写法的问题
你之前的字符串拼接方式:
query = "SELECT * FROM contact WHERE country IN ('{}');".format("', '".join(query["countries"]))
- 当国家名称包含单引号时,会直接破坏SQL语法结构,导致查询报错。
- 若用户传入恶意构造的内容(比如
'); DROP TABLE contact;--),会直接执行危险的SQL操作,引发数据安全问题。
内容的提问来源于stack exchange,提问作者Gaut
相关产品推荐
相关产品推荐

