Skip to main content
 首页 » 编程设计

python之Django:SQL 防注入(inject)管理器.py

2025年05月04日28bhlsheji

我有一个 managers.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) 

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

变量“field”被解析以确保它属于一组合法值,但这种检查是在 View 中完成的。例如:

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' 

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

那么,有没有一种方法可以在不进行循环导入的情况下根据管理器中的模型字段验证参数?也就是说,经理需要导入模型以获取允许的字段列表,但模型需要导入经理。

请您参考如下方法:

在extra中使用select_params避免了sql注入(inject):

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)