将用户输入的数据传递给 Queryset.filter() - 是否安全



我有一个页面,它从它的网址中获取GET参数,并将这些参数直接传递给REST API。因此,页面URL如下所示:

foo.com/pizzas/?toppings=mushrooms&toppings=sausage

当页面加载时,它将获取GET参数并将它们传递给REST API,如下所示:

foo.com/totally/unrelated/url/?toppings=mushrooms&toppings=sausage

在后端,我想提取这些并根据它们进行过滤。这基本上是我现在拥有的:

# inside a django rest framework ModelViewSet
#   it's not really relevant other than that self.request exists
def get_queryset(self):
    queryset = self.model.objects.all()
    for param in self.request.query_params:
        # param = "toppings"
        if not self.is_real_model_field(param):  # assume this works
            continue
        param_value_list = self.request.query_params.getlist(param)
        # param_value_list = ['mushrooms', 'sausage']
        queryset = queryset.filter(
            f"{param}__in": param_value_list
        )
    return queryset

我已经说过它是Django Rest框架这一事实无关紧要,但我不是100%确定这一点。在上面的例子中,request.query_params是由 Django Rest Framework 添加的,但根据 DRF 的文档,我相信它只是 django 内置request.GET的别名。

那么,这在 Django 中安全吗?恶意行为者可以直接操纵 URL。我假设 django 的QuerySet.filter(field__in: values)会自动为您进行一些清理,和/或 URL 的有限字符集将有助于阻止任何令人讨厌的事情出现,但我无法找到任何讨论该问题的资源。

看看django_filters包。它可以做你想要的,你不需要重新发明轮子。

使用此包,您可以列出所有可过滤的字段。此包还添加了查询参数值验证。

最新更新