You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向Python SQLite表插入数据时清理用户输入的正确方法是什么?

SQLite Python 开发防SQL注入最佳实践

1 为什么你找到的「安全示例」运行报错

你找到的安全示例是适配MySQL、PostgreSQL等数据库的写法,这类数据库的参数占位符用%s,但SQLite 不支持%s作为参数占位符,所以才会抛出sqlite3.OperationalError: near "%": syntax error语法错误。

SQLite支持两种参数占位符格式:

  • 问号占位符:?,按顺序传参
  • 命名占位符::参数名,按字典传参

2 你当前的黑名单过滤方案存在的问题

黑名单过滤是极低效的SQL注入防护手段,存在两个核心缺陷:

  • 极易被绕过:攻击者可以通过编码变形、大小写组合、特殊字符拼接等多种方式绕过你的黑名单规则,你永远无法穷举所有恶意字符
  • 影响业务正常使用:如果业务允许用户名或地址包含'、\这类合法字符,你的替换逻辑会直接破坏原始输入的正确性

3 防SQL注入的正确方案

防SQL注入的唯一核心最佳实践是使用参数化查询(预编译语句),不需要你自己实现任何SQL特殊字符过滤逻辑,数据库驱动会自动处理所有参数的转义,从根本上杜绝注入风险。

3.1 参数化查询的本质区别

  • 错误写法(字符串拼接):将用户输入和SQL语句结构拼在一起,用户输入的恶意内容会被数据库当成SQL指令的一部分执行
  • 正确写法(参数化查询):SQL语句结构和用户输入完全分离,数据库先编译SQL语句的结构,再将参数填入对应位置,参数的内容永远只会被当成普通值处理,不会被解析为SQL指令

3.2 SQLite 正确写法示例

查询示例

# 问号占位符写法
cursor.execute("SELECT admin FROM users WHERE username = ?", (username,))
# 命名占位符写法
cursor.execute("SELECT admin FROM users WHERE username = :username", {"username": username})

插入数据示例(适配你的业务场景)

import sqlite3

def insert_data(userID, username, location):
    # 业务规则校验(仅为了符合业务要求,不是防注入的必须步骤)
    user_id_str = str(userID)
    # 注意原代码的逻辑判断错误:要用or而不是and,否则会出现校验不生效的问题
    if not user_id_str.isdecimal() or len(user_id_str) != 18:
        raise ValueError("userID必须为18位纯数字")
    if len(username) > 32:
        raise ValueError("用户名长度不能超过32位")
    if len(location) > 64:
        raise ValueError("地址长度不能超过64位")
    
    # 连接数据库执行参数化插入
    conn = sqlite3.connect("your_database.db")
    cursor = conn.cursor()
    cursor.execute(
        "INSERT INTO users (userID, username, location) VALUES (?, ?, ?)",
        (user_id_str, username, location)
    )
    conn.commit()
    conn.close()

3.3 补充建议

业务层面的格式校验可以保留,用于提前拦截不符合要求的输入,减少无效的数据库请求,但不要依赖业务校验做SQL注入防护,防注入的核心必须是参数化查询。

内容的提问来源于stack exchange,提问作者Ventus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:54:05