【问题标题】:Why should MySQL Connector cursor.execute() params be variables?为什么 MySQL 连接器 cursor.execute() 参数应该是变量?
【发布时间】:2021-04-25 09:39:42
【问题描述】:

我正在尝试使用 MySQL 连接器为我的 API 创建一个过滤器。 我处理用户生成的查询,如下所示:

user_type_id > 1 并在WHERE 子句中使用它们。

由于查询来自用户,我想将它们作为参数传递给 cursor.execute(query, params) 以避免注入。

当我跑步时

cursor.execute("SELECT * FROM table WHERE %s > %s", ('user_type_id', 1))

它没有按我的意愿工作。

Documentation 声明

参数绑定到操作中的变量。

由于他们不允许 params 包含除变量(例如列名)以外的任何内容,我想这是有原因的。

你能告诉我只允许变量作为参数传递的原因吗? 我也想知道这个问题有没有好的解决方法?

【问题讨论】:

    标签: python mysql python-3.x mysql-python


    【解决方案1】:

    您希望用户能够生成三件事:

    • 字段(不能参数化a,看起来这些对应于数据库中的列名)
    • 比较器(无法参数化)
    • 字段的值 (可以参数化)

    幸运的是,字段和比较器的值集非常有限。你能建立一个列表,然后在将它们连接到查询之前自己验证它们吗?

    类似:

    def create_query(
        field: str, comparator: str, field_value: int
    ) -> typing.Tuple[str, typing.Tuple]:
        allowed_fields = ("user_type_id", "user_age")  # for example
        allowed_comparators = (">", "<", "=")
        if field not in allowed_fields:
            raise ValueError(f"{field!r} not in allowed_fields {allowed_fields!r}")
        if comparator not in allowed_comparators:
            raise ValueError(
                f"{comparator!r} not in allowed_comparators {allowed_comparators!r}"
            )
    
        return f"SELECT * FROM table WHERE {field} {comparator} %s", (field_value,)
    

    上述内容不能被 SQL 注入,因为您在追加到查询之前检查了严格的白名单,并且您可以枚举这些字符串的所有可能值。您只需非常警惕,您可以检查所有可能的字段。

    注意:虽然我认为这是做这样的事情的唯一方法并且它是安全的,但我还没有在使用它的生产系统上工作过,我非常想知道是否有人可以找到问题上面的函数

    【讨论】:

    • 感谢您的好主意!您认为不允许对比较器或字段进行参数化的原因是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 2013-08-09
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多