Python SQLite3如何基于用户输入安全查询表且无SQL注入风险?
SQL注入风险规避方案
核心原因说明
参数化查询的占位符仅支持传入数据值,会自动对传入内容加引号、做数据值层面的转义,而表名属于SQL标识符,不能被当作字符串值处理,所以直接用?传表名会触发语法错误。
可行解决方案
- 白名单校验(最推荐,安全性最高)
提前在后端枚举所有允许用户访问的表名列表,用户传入的selected_table必须严格匹配白名单内的元素才能执行后续查询,完全杜绝非法表名传入。
示例逻辑:# 替换为实际允许用户访问的表名集合 ALLOWED_TABLES = {"user_info", "order_record", "product_list"} selected_table = selected_table.strip() if selected_table not in ALLOWED_TABLES: raise PermissionError("访问的表不存在或无权限") # 校验通过后再执行查询 cursor.execute("SELECT * FROM {0} ".format(selected_table)) - 使用数据库驱动自带的标识符转义方法
绝大多数数据库的Python驱动都提供了专门针对SQL标识符(表名、列名)的转义工具,会自动处理特殊字符、添加规范的标识符包裹符号,避免注入风险。
不同驱动示例:- PostgreSQL(psycopg2):
from psycopg2 import sql cursor.execute(sql.SQL("SELECT * FROM {}").format(sql.Identifier(selected_table))) - MySQL(PyMySQL):
escaped_table = connection.escape_string(selected_table) cursor.execute(f"SELECT * FROM `{escaped_table}`") - SQLite:
escaped_table = conn.quote(selected_table) cursor.execute(f"SELECT * FROM {escaped_table}")
- PostgreSQL(psycopg2):
- 系统表校验(适合表列表变动频繁的场景)
先从数据库的系统表中查询当前库下所有合法的用户表名,校验用户传入的表名是否真实存在,再执行查询。比如MySQL可以查询information_schema.TABLES表,PostgreSQL查询pg_tables表。
内容的提问来源于stack exchange,提问作者Gaven
相关产品推荐
相关产品推荐

