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

如何在SQLModel的JSONPATH查询中避免SQL注入?

解决SQLModel中JSON路径查询的SQL注入问题

问题根源

你的代码直接将用户输入的value字符串拼接进JSON路径表达式,导致攻击者可以通过构造恶意输入篡改查询逻辑。比如传入value='"' || ""=="'"时,最终的JSON路径会变成:

$[*] ? (@.id == "stg") ? (@.val == "" || ""=="")

这个表达式会恒为真,完全绕过原本的查询限制。

最优解决方案:使用参数化JSON路径

PostgreSQL的jsonb_path_exists支持参数化JSON路径,可以通过传递JSON格式的参数对象安全引用外部值,彻底避免字符串拼接带来的注入风险。SQLModel完全兼容这种用法,具体实现如下:

代码示例

from sqlmodel import Session, func, select

def some_fn(session: Session, value: str) -> list[DbItem]:
    statement = select(DbItem).where(
        func.jsonb_path_exists(
            DbItem.json_field,
            # 在JSON路径中用$val作为参数占位符
            '$[*] ? (@.id == "stg") ? (@.val == $val)',
            # 构建参数对象,将value绑定到$val变量
            func.jsonb_build_object('val', value)
        ),
    )
    return session.exec(statement).all()

原理说明

  1. 参数化占位符:在JSON路径中用$val标记需要外部传入的参数,替代直接字符串拼接。
  2. 安全参数传递:通过func.jsonb_build_object('val', value)构造JSON参数对象,将用户输入的value作为数据库参数传递。数据库会自动对参数进行转义和绑定,不会将其解析为JSON路径的执行逻辑。
  3. 注入防护:无论用户输入什么内容,都会被当作普通字符串处理,无法篡改原有的查询逻辑。

备选方案:显式绑定参数(复杂场景适用)

如果需要更清晰地控制参数绑定逻辑,可以使用sqlmodel.bindparam显式声明参数:

from sqlmodel import Session, func, select, bindparam

def some_fn(session: Session, value: str) -> list[DbItem]:
    # 显式绑定参数
    value_param = bindparam("target_val", value=value)
    statement = select(DbItem).where(
        func.jsonb_path_exists(
            DbItem.json_field,
            '$[*] ? (@.id == "stg") ? (@.val == $target_val)',
            func.jsonb_build_object('target_val', value_param)
        ),
    )
    return session.exec(statement).all()

这种方式在多参数、复杂查询场景下更易维护,便于排查参数绑定问题。


内容的提问来源于stack exchange,提问作者László Ács

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:27:12