Django 有一个用`method=='POST':`检查每个视图的好处
Django is there a benefit of checking every view with `method=='POST':`
以 if request.method=='POST':
或 if request.method=='GET':
启动我的每个视图函数是否有好处?或者我只是添加不必要的代码行?
我遵循了几个示例,其中 Ajax 的视图都在检查 HTTP 是否使用 GET 生成。
例如,它能否阻止 DDOS 锁定 POST 方法并使用 GET 对其进行攻击?或者,更实际地,防止 API 消费者在应该 PUT 或 POST?
时错误地 PATCHing
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':
Is there a benefit to starting every one of my view functions with if request.method=='POST':
是的,就算你只支持一种方法,也要守住这个。 HTTP 协议指定 GET 请求不应该有副作用(在计算访问者的意义上的良好效果可能没有问题,但严格来说不会改变业务逻辑的 "entities" 的东西是不可接受的)。
现在 "web crawlers"(例如搜索引擎或爬虫使用的)通常会检测页面上的链接,并对这些链接发出 GET 请求(因为它们的目标是 "discover" 新页面)。如果此 URL 背后有一个视图,例如,删除一名员工,则可能 意外地 一个 "web crawler" 将编辑您的数据库。
其他方法如 GET
、HEAD
、PUT
和 DELETE
应该是 idempotent(这意味着使两次相同的请求,应该具有与只发出一次请求相同的副作用。
因此,如果不 "protecting" 您的观点,您将失去一层 "protection" 以防止意外滥用您的网络服务器。
黑客还可以使用另一种方法发出请求,并查看服务器如何响应搜索以查找漏洞利用:例如,查看服务器是否对执行 DELETE 时失败的方法做出某些假设要求。例如,一个处理所有方法的相当通用的视图实现,如果不加以保护,可能会无意中允许删除文件(例如,您编写一个通用视图来创建和编辑内容可能会被黑客 "misused" 使用DELETE
请求实现父视图,但不应为该特定实体提供支持)。
在早期,一些 HTTP 网络服务器在使用 HEAD 请求时不检查身份验证。因此,黑客可以通过尝试多次 HEAD 请求 "scan" id space,从而了解数据库中填充了哪些 id。当然,它本身不会泄露 很多 数据,但它是一个可以 使用 作为黑客数据第一步的漏洞。
请注意,虽然 Django 在使用例如基于 class 的视图时有 一些 保护,但一个人可以只使用 any 请求的字符串。所以一个人可以写成方法FOOBAR
。例如,如果视图指定 if request.method == 'POST'
和 else:
语句,则可以使用它以非 GET 方法输入 else
语句。
但不管用例如何,"better be safe than sorry" 和保护 HTTP 方法只是要检查的方面之一。
也就是说,如果只允许一部分方法,您可以使用 @require_http_methods
[Django-doc] 装饰器:
from django.views.decorators.http import require_http_methods
<b>@require_http_methods(["GET", "POST"])</b>
def my_view(request):
# I can assume now that only GET or POST requests make it this far
# ...
pass
因此,这个装饰器可以更优雅地保护使用了正确的方法。
为了提供一个不同的视角,我认为你的问题说明了为什么你应该考虑使用基于 class 的视图,这使得处理此类问题时的生活变得更加简单。
例如,通用 CreateView 已经带有所有内置逻辑来限制 HTTP 请求的类型。它会让您执行 GET 请求来初始化表单,但需要 POST 请求来处理数据。因此,您不会意外触发通过 GET 请求保存数据。
它还提供了适当的表单数据验证、错误处理等框架——您必须在过程视图中自行实现。
Django 提供的其他视图范围也是如此 - UpdateView
、DetailView
等
所有基于 Django class 的视图都带有一个 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.
除了为表单处理、模板加载等事情提供许多其他帮助之外,过程化视图最初可能 感觉 更简单,但您很快就会意识到您结束了不得不写更多的代码来让他们做你需要的事情。
以 if request.method=='POST':
或 if request.method=='GET':
启动我的每个视图函数是否有好处?或者我只是添加不必要的代码行?
我遵循了几个示例,其中 Ajax 的视图都在检查 HTTP 是否使用 GET 生成。
例如,它能否阻止 DDOS 锁定 POST 方法并使用 GET 对其进行攻击?或者,更实际地,防止 API 消费者在应该 PUT 或 POST?
时错误地 PATCHingdef 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':
Is there a benefit to starting every one of my view functions with if
request.method=='POST':
是的,就算你只支持一种方法,也要守住这个。 HTTP 协议指定 GET 请求不应该有副作用(在计算访问者的意义上的良好效果可能没有问题,但严格来说不会改变业务逻辑的 "entities" 的东西是不可接受的)。
现在 "web crawlers"(例如搜索引擎或爬虫使用的)通常会检测页面上的链接,并对这些链接发出 GET 请求(因为它们的目标是 "discover" 新页面)。如果此 URL 背后有一个视图,例如,删除一名员工,则可能 意外地 一个 "web crawler" 将编辑您的数据库。
其他方法如 GET
、HEAD
、PUT
和 DELETE
应该是 idempotent(这意味着使两次相同的请求,应该具有与只发出一次请求相同的副作用。
因此,如果不 "protecting" 您的观点,您将失去一层 "protection" 以防止意外滥用您的网络服务器。
黑客还可以使用另一种方法发出请求,并查看服务器如何响应搜索以查找漏洞利用:例如,查看服务器是否对执行 DELETE 时失败的方法做出某些假设要求。例如,一个处理所有方法的相当通用的视图实现,如果不加以保护,可能会无意中允许删除文件(例如,您编写一个通用视图来创建和编辑内容可能会被黑客 "misused" 使用DELETE
请求实现父视图,但不应为该特定实体提供支持)。
在早期,一些 HTTP 网络服务器在使用 HEAD 请求时不检查身份验证。因此,黑客可以通过尝试多次 HEAD 请求 "scan" id space,从而了解数据库中填充了哪些 id。当然,它本身不会泄露 很多 数据,但它是一个可以 使用 作为黑客数据第一步的漏洞。
请注意,虽然 Django 在使用例如基于 class 的视图时有 一些 保护,但一个人可以只使用 any 请求的字符串。所以一个人可以写成方法FOOBAR
。例如,如果视图指定 if request.method == 'POST'
和 else:
语句,则可以使用它以非 GET 方法输入 else
语句。
但不管用例如何,"better be safe than sorry" 和保护 HTTP 方法只是要检查的方面之一。
也就是说,如果只允许一部分方法,您可以使用 @require_http_methods
[Django-doc] 装饰器:
from django.views.decorators.http import require_http_methods <b>@require_http_methods(["GET", "POST"])</b> def my_view(request): # I can assume now that only GET or POST requests make it this far # ... pass
因此,这个装饰器可以更优雅地保护使用了正确的方法。
为了提供一个不同的视角,我认为你的问题说明了为什么你应该考虑使用基于 class 的视图,这使得处理此类问题时的生活变得更加简单。
例如,通用 CreateView 已经带有所有内置逻辑来限制 HTTP 请求的类型。它会让您执行 GET 请求来初始化表单,但需要 POST 请求来处理数据。因此,您不会意外触发通过 GET 请求保存数据。
它还提供了适当的表单数据验证、错误处理等框架——您必须在过程视图中自行实现。
Django 提供的其他视图范围也是如此 - UpdateView
、DetailView
等
所有基于 Django class 的视图都带有一个 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.
除了为表单处理、模板加载等事情提供许多其他帮助之外,过程化视图最初可能 感觉 更简单,但您很快就会意识到您结束了不得不写更多的代码来让他们做你需要的事情。