Django有一个用`method =='POST'检查每个视图的好处:

时间:2018-09-22 20:22:43

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

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

我遵循了一些示例,其中所有Ajax的视图都在检查HTTP是否使用GET进行。

例如,是否可以防止DDOS闩锁到POST方法并用GET重击它?或者,实际上,是防止API使用者在应该进行PUT或POST时错误地进行PATCH处理?

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':

2 个答案:

答案 0 :(得分:7)

  

使用request.method=='POST':

启动我的每个视图功能是否有好处?

,即使您仅支持一种方法,也最好对此加以保护。 HTTP协议规定GET请求不应具有副作用(在统计访问者的意义上,良好的效果可能没有问题,但严格来讲,不能改变业务逻辑的“实体”的事物是不可接受的。)

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

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

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

黑客还可以瞄准使用另一种方法发出请求,并查看服务器如何响应搜索以发现漏洞:例如,查看服务器是否对该方法做出某些假设,这些假设在执行DELETE请求时会失败。例如,一个处理所有方法的通用视图实现可能(如果不受保护)会无意间允许删除文件(例如,您编写通用视图来创建和编辑内容可能会被黑客“ { {1}}请求实现父视图,但该特定实体不应该支持该父视图。

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

请注意,尽管Django在使用例如基于类的视图时对此有 some 保护,但一个人只能对请求使用 any 字符串。因此,一个人可以将其写为方法DELETE。例如,如果视图指定了FOOBAR和一个if request.method == 'POST'语句,则可以使用该视图通过非GET方法输入else:语句。

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

话虽如此,如果只允许方法的子集,则可以使用@require_http_methods [Django-doc]装饰器:

else

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

答案 1 :(得分: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.

这不仅为表单处理,模板加载等提供了许多其他帮助程序。过程视图最初可能感觉更简单,但是您很快就会意识到自己最终不得不编写一个更多的代码可以使他们完成所需的工作。