Python使用aiosqlite查询sqlite3时如何安全将表名作为参数
你使用?占位符报错的核心原因是:SQLite的参数占位符仅支持值类型的参数绑定,表名、列名属于SQL标识符,不属于动态值范畴,无法通过参数占位符传入。你在SQL中用单引号包裹?的写法,相当于直接把?当成了表名的字面量,自然会触发no such table: ?的报错。
要实现动态表名的安全传入,推荐使用「白名单校验+标识符转义」的组合方案,从根源规避SQL注入风险,具体实现如下:
第一步:实现白名单校验逻辑
先查询当前数据库中所有已存在的表名,校验你要传入的表名确实是合法存在的,直接拦截恶意伪造的表名:
async def get_all_tables(conn): # 从sqlite系统表查询所有用户表 cursor = await conn.execute("SELECT name FROM sqlite_master WHERE type='table';") return {item[0] for item in await cursor.fetchall()}
第二步:标识符转义后拼接SQL
按照SQLite的标识符转义规则,将表名中的双引号替换为两个双引号,再用双引号包裹整个表名,避免表名中存在特殊字符时被解析为SQL语句片段:
t = '2c2c33d6-6eb2-4040-959f-08821942e1af' all_tables = await get_all_tables(dbconn) # 白名单校验 if t not in all_tables: raise ValueError(f"不存在的表名:{t}") # 转义处理表名 safe_table = f'"{t.replace("\"", "\"\"")}"' # 拼接执行SQL cursor = await dbconn.execute(f"SELECT obstmstmp FROM {safe_table} ORDER BY obstmstmp DESC LIMIT 1;") obstmstmp = (await cursor.fetchone())[0]
补充说明
如果你的场景中表名固定为UUID格式,本身就不存在空格、引号、特殊符号,也可以省略转义步骤,但白名单校验依然建议保留,作为双重安全保障。
内容的提问来源于stack exchange,提问作者e-pirate
相关产品推荐
相关产品推荐

