You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将用户输入数据传入Django QuerySet.filter()是否安全?

你的Django过滤实现是否安全?

好问题!你的这种实现方式在Django里是安全的,不用担心SQL注入或其他常见恶意攻击,原因主要有以下几点:

1. Django ORM的参数化查询自动防护

Django的QuerySet底层使用了参数化查询机制,不管你是用字段名还是用户传入的参数值,都会被ORM安全处理,不会直接拼接到SQL语句中。

比如你代码里的filter(f"{param}__in": param_value_list),Django会先验证字段名的合法性(配合你的is_real_model_field检查就更稳妥),然后把param_value_list作为参数传递给数据库——哪怕用户传入了带特殊字符的参数值,也只会被当作普通字符串处理,完全避免了SQL注入的风险。

2. request.query_params的安全处理

不管是DRF的request.query_params还是Django原生的request.GET,它们都是经过Django处理的QueryDict对象,用户传入的任何特殊字符都会被自动转义,不会直接作为可执行代码或恶意SQL的一部分。

而且你已经通过is_real_model_field过滤了非模型字段的参数,这进一步缩小了用户能操作的范围,防止他们传入不存在的字段名来尝试构造攻击。

额外的安全优化建议

虽然当前实现已经安全,但可以做一些优化让它更健壮:

  • 用Django内置字段验证替代自定义检查:
    你可以用Django模型的_meta.get_field()来实现更可靠的字段校验,避免自定义逻辑可能出现的疏漏:

    from django.core.exceptions import FieldDoesNotExist
    
    def is_real_model_field(self, param):
        try:
            self.model._meta.get_field(param)
            return True
        except FieldDoesNotExist:
            return False
    
  • 添加字段白名单:
    如果不是所有模型字段都允许用户过滤,可以定义一个白名单,只开放特定字段:

    ALLOWED_FILTER_FIELDS = ["toppings", "size", "crust_type"]
    if param not in ALLOWED_FILTER_FIELDS:
        continue
    

    这种方式能更精细地控制用户的操作权限,避免敏感字段被意外暴露。

  • 参数值类型校验:
    如果你的字段是特定类型(比如整数、日期),可以尝试把参数值转换成对应类型,避免无效输入导致的错误:

    if param == "size":
        try:
            param_value_list = [int(val) for val in param_value_list]
        except ValueError:
            # 处理无效输入,比如跳过该参数或返回错误响应
            continue
    

内容的提问来源于stack exchange,提问作者Daniel Smedema

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:15:52