2

我有一个 manager.py 文件,它使用 .extra() 参数来执行原始 SQL 查询。例如:

class MyManager(models.Manager):

    def order_null_last(self, field):
        return super(DecisionManager, self).get_query_set()\
            .extra(select={'has_field': "CASE WHEN " + field + " IS NULL THEN 1 ELSE 0 END"}).order_by('has_field', field)

有人向我建议,这种查询可能容易受到注入攻击。

解析变量“字段”以确保它属于一组合法值,但此检查是在视图中完成的。例如:

class ModelList(ListView):
    model = MyModel

    def get(self, request, *args, **kwargs):
        self.set_sorting(request)

    def set_sorting(self, request):
        self.sort_field = request.GET.get('sort', '-id')
        if not self.sort_field in self.sort_options:
            self.sort_field = 'id'

因此,如果有人使用上述管理器编写了一个新视图,但他们忘记过滤参数,那么漏洞利用是可能的。

那么,有没有一种方法可以在不循环导入的情况下针对管理器中的模型字段验证参数?也就是manager需要导入model来获取允许字段列表,但是model需要importmanager。

4

2 回答 2

1

在 extra 中使用 select_params 可以避免 sql 注入:

class MyManager(models.Manager):

def order_null_last(self, field):
    return super(DecisionManager, self).get_query_set()\
        .extra(select={'has_field': "CASE WHEN %s IS NULL THEN 1 ELSE 0 END"}, select_params=(field,)).order_by('has_field', field)
于 2012-11-13T18:24:12.917 回答
0

模型管理器可以访问模型,因此可以通过 self.model 访问字段。

所以我可以这样写:

MyManager 类(models.Manager):

def order_null_last(self, field):
    if field in [modelfield.name for modelfield in self.model._meta.fields]:
        return super(DecisionManager, self).get_query_set()\
            .extra(select={'has_field': "CASE WHEN " + field + " IS NULL THEN 1 ELSE 0 END"}).order_by('has_field', field)
    else:
        return super(DecisionManager, self).get_query_set()
于 2012-12-07T11:44:33.950 回答