首页 > 解决方案 > 使用字符串连接+eval() 来构建 SQLAlchemy 查询可以吗,还是有更好的选择?

问题描述

我使用 React-Admin 作为我的前端,它使用 Flask-Restful 调用我的 API。

当我使用过滤器时,它会在字典中发送一个键值对。根据一次使用的过滤器数量,我的 API 可能会请求 0 到 3 个键值对。

我已经成功地使用了一系列 if 语句来查看键是否在 dict 中,以及是否将过滤器的相应部分添加到查询中。

但是,我听说使用 eval() 是不安全的,因为其他人可以将代码注入您的应用程序。我相信当我正在设置字符串时,这是不可能的。这是安全使用还是有更好的方法来使用flask-sqlalchemy设置查询?

    def find_all(cls, sort, fltr):
        order = sort[1]
        if order == 'ASC':
            s = sort[0]
        else:
            s = sort[0] + " desc"
        query_name = "cls.query."
        if "T" in fltr:
            query_name += 'filter(cls.title.like("%"+fltr["T"]+"%")).'
        if "c" in fltr:
            if fltr['c']:
                query_name += "filter_by(complete=False)."
        if "a" in fltr:
            query_name += 'filter(cls.assigned_id.like("%"+str(fltr["a"])+"%")).'
        query_name += 'order_by(s).all()'
        return eval(query_name)

fltr字典在哪里。

这工作正常,但在 web 应用程序中使用是否安全?

标签: pythonflaskflask-sqlalchemy

解决方案


这里有两个不同的问题。


安全吗?

因为查询只能由您自己编写和审核的常量子字符串组成的段组成,的。如果您曾经将用户提供的数据替换到这些查询中,那将不再适用。


这是好习惯吗?

绝对不。存在性能损失、可读性损失、正确性损失(就静态检查工具无法读取隐藏在 AST 后面的语句的情况而言eval()),并且如果将来其他人想要替换用户提供的数据,则原始代码会使他们更容易走字符串替换路线并在以后引入漏洞。

改为考虑:

    def find_all(cls, sort, fltr):
        order = sort[1]
        if order == 'ASC':
            s = sort[0]
        else:
            s = sort[0] + " desc"
        q = cls.query
        if "T" in fltr:
            q = q.filter(cls.title.like("%"+fltr["T"]+"%"))
        if "c" in fltr and fltr['c']:
            q = q.filter_by(complete=False)
        if "a" in fltr:
            q = q.filter(cls.assigned_id.like("%"+str(fltr["a"])+"%"))
        return q.order_by(s).all()

推荐阅读