【问题标题】:Django is there a benefit of checking every view with `method=='POST':`Django 使用 `method=='POST' 检查每个视图有什么好处:`
【发布时间】:2018-09-23 13:22:15
【问题描述】:

使用if request.method=='POST':if request.method=='GET': 启动我的每一个视图函数是否有好处?还是我只是添加不必要的代码行?

我遵循了几个示例,其中 Ajax 的视图都在检查 HTTP 是否是使用 GET 生成的。

例如,它能否阻止 DDOS 锁定 POST 方法并使用 GET 攻击它?或者,更实际地,防止 API 使用者在应该 PUT 或 POST 时错误地修补?

def employee_delete(request, uid):
    if request.method == 'DELETE':

def employee_detail(request, uid):
    if request.method == 'GET':

def employee_create(request):
    if request.method == 'POST':

def employee_update(request, uid):
    if request.method == 'PUT':

【问题讨论】:

  • 你可以使用@require_http_method(..)装饰器docs.djangoproject.com/en/2.1/topics/http/decorators/…
  • 但这可能是个好主意的原因是因为GET 不应该有副作用,如果“互联网蜘蛛”(机器人)或用户不小心访问了@987654327 @链接通过GET,员工被删除。

标签: django rest django-rest-framework django-views api-design


【解决方案1】:

使用 if request.method=='POST': 启动我的每个视图函数是否有好处

是的,即使你只支持一种方法,也最好注意这一点。 HTTP 协议规定 GET 请求不应该有副作用(在计算访问者的意义上的良好效果可能没有问题,但没有改变业务逻辑的“实体”的东西严格来说是不可接受的)。

现在“网络爬虫”(例如由搜索引擎或抓取工具使用)通常会检测页面上的链接,并对这些链接发出 GET 请求(因为它们旨在“发现”新页面)。如果此 URL 后面有一个视图,例如删除员工,则可能会发生 意外“网络爬虫”会编辑您的数据库。

GETHEADPUTDELETE 等其他方法应该是幂等的(这意味着两次发出相同的请求,应该具有相同的副作用,如只发出一次请求)。

因此,如果不“保护”您的视图,您将失去一层“保护”,防止意外滥用您的网络服务器。

黑客还可以通过其他方法发出请求,并查看服务器在搜索中如何响应以查找漏洞:例如,查看服务器是否对执行 DELETE 请求时失败的方法做出某些假设。例如,处理所有方法的相当通用的视图实现,如果不加以保护,可能会无意中允许删除文件(例如,您编写通用视图来创建和编辑内容可能会被黑客“滥用”使用 @ 987654327@ 请求实现父视图,但该特定实体不应支持)。

在早期,例如一些 HTTP 网络服务器在使用 HEAD 请求时不会检查身份验证。结果,黑客可以通过尝试几个 HEAD 请求“扫描”id 空间,从而了解数据库中填充了哪些 id。当然,这本身并不会泄露太多数据,但它是一个漏洞,可以使用作为黑客数据的第一步。

请注意,尽管 Django 在使用例如基于类的视图时有一些 保护,但人们可以只使用 any 字符串作为请求。所以一个人可以写成方法FOOBAR。例如,如果视图指定if request.method == 'POST'else: 语句,则可以使用它以非GET 方法输入else 语句。

但不管用例如何,“安全胜于遗憾”以及保护 HTTP 方法只是要检查的方面之一。

话虽如此,如果只允许一部分方法,您可以使用@require_http_methods [Django-doc] 装饰器:

from django.views.decorators.http import require_http_methods

@require_http_methods(["GET", "POST"])
def my_view(request):
    # I can assume now that only GET or POST requests make it this far
    # ...
    pass

因此,这个装饰器可以更优雅地保护使用正确的方法。

【讨论】:

    【解决方案2】:

    为了提供不同的观点,我认为您的问题说明了为什么您应该考虑使用基于类的视图,这使得处理此类问题时的生活变得如此简单。

    例如,通用的CreateView 已经内置了所有逻辑来限制 HTTP 请求的类型。它将允许您执行 GET 请求来初始化表单,但需要 POST 请求来处理数据。因此,您不会意外触发通过 GET 请求保存数据。

    它还为正确的表单数据验证、错误处理等提供了框架——您必须在程序视图中自己实现这些。

    Django 提供的其他视图范围也是如此 - UpdateViewDetailView 等。

    所有基于 Django 类的视图都带有一个 http_method_names 属性,您可以使用该属性来控制视图上允许哪些方法,例如,

    from django.views.generic import View
    
    class MyView(View):
    
        # only GET and POST allowed. Anything else will get a 405 Method Not Allowed response.
        http_method_names = ['get', 'post']
    
        def get(self, request, *args, **kwargs):
            # Logic for GET requests goes here.
    
        def post(self, request, *args, **kwargs):
            # Logic for POST requests goes here. No risk of it getting mixed up with GET.
    

    除了为表单处理、模板加载等提供许多其他帮助程序之外。过程视图最初可能感觉更简单,但你很快就会意识到你最终不得不编写一个更多的代码让他们做你需要的事情。

    【讨论】:

    • 谢谢!所以看起来表单字段可以在 CreateView 中指定。视图中是否也会出现字段清理和错误消息? docs.djangoproject.com/en/2.1/topics/class-based-views/…
    • 是的,您可以通过在视图上设置fields 属性来指定CreateView 公开的字段。是的,它将根据您的模型定义处理字段的清理和验证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 2012-11-28
    相关资源
    最近更新 更多