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

QSqlTableModel执行参数化查询防范SQL注入的问题排查

QSqlTableModel实现LIKE模糊查询并防范SQL注入的正确方案

现有方案问题分析

  • 尝试1(字符串拼接SQL):直接将用户输入通过字符串拼接嵌入SQL语句,没有任何转义逻辑,属于典型的SQL注入漏洞写法,用户输入的单引号、UNION语句等可以直接篡改SQL执行逻辑,必须完全废弃。
  • 尝试2(setFilter拼接字符串):两个核心错误:① 手动调用setQuery()传入自定义查询后,setFilter()方法完全不生效——setFilter()仅在模型自动生成查询语句(未手动传入自定义query、通过setTable()指定表名)时才会在select()阶段拼接过滤条件;② 传入setFilter()的内容依然是字符串拼接用户输入,本身仍存在SQL注入风险。
  • 尝试3(参数绑定但执行逻辑错误):参数绑定的思路是正确的,但存在两个流程错误:① 完成prepare()和bindValue()后没有调用q.exec()执行查询,传入setQuery()的是未执行的空查询对象;② 传入自定义query后又调用model->select(),会触发模型自动生成默认查询覆盖你手动设置的结果集,最终导致无数据返回。

正确实现代码

方案1(推荐,官方原生写法,无注入风险)

优先使用QSqlTableModel原生的表映射能力,不需要手动编写全量SELECT语句,通过官方提供的参数绑定接口传值,从根源避免注入,同时保留模型所有内置的增删改、排序、分页能力(Qt 5.14及以上版本支持):

// 初始化模型时传入数据库连接对象,避免使用默认连接的坑
SqlTableModel *model = new SqlTableModel(this, db);
model->setTable("table"); // 直接指定查询的表名,模型自动生成合规SQL

// 过滤条件用?做占位符,绝对不要拼接用户输入
model->setFilter("col LIKE ? ESCAPE '\\\\'");
// 绑定参数:先转义用户输入中自带的LIKE通配符,再拼接查询用的%通配符
QString keyword = edit->text().trimmed();
keyword.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");
model->setQueryParameters(QSql(), {QString("%%1%").arg(keyword)});

// 执行查询,必须加错误判断
if (!model->select()) {
    qDebug() << "查询失败:" << model->lastError().text();
    return;
}
tableView->setModel(model);

方案2(兼容低版本Qt,自定义参数化查询)

如果使用Qt 5.14以下版本,可手动编写参数化查询,严格按照prepare->bindValue->exec的流程执行成功后再传入模型:

QSqlQuery q(db);
// 编写参数化SQL,禁止拼接任何用户输入内容
q.prepare("SELECT * FROM table WHERE col LIKE :param ESCAPE '\\\\'");
// 处理用户输入关键词
QString keyword = edit->text().trimmed();
keyword.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");
// 绑定带查询通配符的参数
q.bindValue(":param", QString("%%1%").arg(keyword));

// 必须先执行查询,确认成功后再传给模型
if (!q.exec()) {
    qDebug() << "SQL执行失败:" << q.lastError().text();
    return;
}

SqlTableModel *model = new SqlTableModel(this);
model->setQuery(q);
// 不需要再调用model->select(),否则会覆盖已有查询结果
if (model->lastError().isValid()) {
    qDebug() << "模型加载失败:" << model->lastError().text();
    return;
}
tableView->setModel(model);

注意:该方案下QSqlTableModel的自动编辑回写、按字段排序等能力会受限,如果需要表格编辑功能请优先使用方案1。

核心安全规则

  • 所有来自用户输入、外部接口的参数,永远不要通过QString::arg()、字符串拼接的方式直接嵌入SQL语句或filter条件,必须使用参数绑定传值,Qt数据库驱动会自动完成特殊字符转义,彻底阻断SQL注入。
  • 所有数据库操作必须增加错误捕获逻辑,通过lastError()打印错误信息,避免出现无返回、无报错的黑盒问题。
  • 使用LIKE查询时必须转义用户输入中自带的%/_/\特殊字符,避免出现非预期的匹配结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:21:35