python - 使用字符串连接+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 应用程序中使用是否安全?
解决方案
这里有两个不同的问题。
安全吗?
因为查询只能由您自己编写和审核的常量子字符串组成的段组成,是的。如果您曾经将用户提供的数据替换到这些查询中,那将不再适用。
这是好习惯吗?
绝对不。存在性能损失、可读性损失、正确性损失(就静态检查工具无法读取隐藏在 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()
推荐阅读
- android-studio - 禁用/隐藏内部类的 IDE 折叠按钮
- c# - Visual Studio C#:无法使用 IntelliTest 对类中的方法生成单元测试?
- php - Require_once php 在托管程序中不起作用
- php - preg_match_all 使用 php preg_match_all 从 httpd-vhosts.conf 文件 xampp 获取虚拟主机列表
- json - 在 aws 中拆分和合并批处理作业中的 json 文件
- javascript - 如何创建 NodeList 实时循环长度检查器
- laravel - Laravel 在 null 上调用成员函数 validate()
- python - 训练二进制分类器 Tensorflow 时出现错误“不支持将字符串转换为浮点数”?
- azure-ad-b2c - 出现间歇性 ADB2C“错误请求”错误
- angular - 如何在 nbcontextmenu 中创建下拉列表 - Nebular Angular11