Pyres 工作人员对我的视图的 Django POST 请求 - CSRF 令牌

Posted

技术标签:

【中文标题】Pyres 工作人员对我的视图的 Django POST 请求 - CSRF 令牌【英文标题】:Django POST request to my view from Pyres worker - CSRF token 【发布时间】:2013-04-25 16:07:57 【问题描述】:

我正在使用 Pyres 工作人员对用户在表单中输入的数据进行一些处理。它们的处理是通过我的表单上的视图完成的,我向它发出 POST 请求,其中的数据包括要处理的数据和用户的 CSRF 中间件令牌。我的问题是这显然还不够,因为 Django 仍然以 403 禁止拒绝我的请求。

相关代码:

表单处理程序:

def 处理程序(请求): if(request.method == "POST"): if(request.POST.__contains__("taskdata")): #表单的有效帖子 taskdata = escape(request.POST.get("taskdata","")) t = TaskData(data=taskdata, time_added=timezone.now(), token=request.POST.get("csrfmiddlewaretoken","")) t.save() r = ResQ(server="127.0.0.1:6379") r.enqueue(任务数据,t.id) 返回 HttpResponse(t.id) 别的: #表单的无效帖子 提出Http404 别的: 提出Http404

Pyres 工人工作:

@静态方法 def 执行(taskData_id): #从这个id获取taskData,测试它是否有任务 task_data = TaskData.objects.get(pk=taskData_id) post_data = [('id',task_data.id),('data',task_data.data), ('csrfmiddlewaretoken',task_data.token)] # 两个元素元组的序列 结果 = urllib2.urlopen('http://127.0.0.1:8000/tasks/nlp/process/', urllib.urlencode(post_data)) 内容 = 结果.read() 返回

该职位发布到的视图:

def进程(请求): if(request.method == "POST"): return HttpResponse("嘿,它有效!") if(request.POST.__contains__("data") 和 request.POST.__contains__("id")): #有效的帖子到表单的模型 #taskdata = escape(request.POST.get("taskdata","")) #data = get_times(任务数据) return HttpResponse("嘿,来自进程!") #return HttpResponse(json.dumps(数据)) 别的: #表单的无效帖子 提出Http404 别的: 提出Http404

我基本上想做的是在提交表单时保存一些原始数据,以及它的 CSRF 令牌。然后工作人员将该数据 + 令牌发送到处理视图。

不幸的是,发布令牌似乎还不够。

有人知道 csrf 保护实际上寻找什么,以及如何使我的 Pyres 工作人员合规吗?

(建议标签:pyres)

【问题讨论】:

handler() 函数是什么?一个 Django 视图,一个中间件函数,还是别的什么? 抱歉,handler() 是一个 Django 视图。它位于表单发布到的 URL 上。 process() 也是一个视图,类似地是一个可发布的 URL(我的 worker perform() 方法在那里发布)。 perform() 方法是模型类上的一个方法,由 Pyres 使用。 【参考方案1】:

我想我看到了问题。

Django's CSRF protection works 的方式是生成一个 nonce,然后将 cookie 设置为 nonce 的值,并确保 csrfmiddlewaretoken POST 值与 cookie 的值匹配。理由是它使它成为一个无状态系统,无需任何持久会话数据即可工作。

问题是您在 Pyres 工作人员作业中提出的请求...

result = urllib2.urlopen('http://127.0.0.1:8000/tasks/nlp/process/', 
                         urllib.urlencode(post_data))

...来自服务器,而不是客户端,所以它不会设置 cookie。

假设/tasks/nlp/process/ URL 受到保护,只能由服务器访问,那么最简单的方法是使用...制作process() 视图exempt from CSRF checking...

@csrf_exempt
def process(request):
   ...

...否则您将不得不手动获取 handler() 视图中的 cookie 值,并将其传递给 Pyres worker 作业。

更新

为确保process() 方法只能由服务器调用,一种简单的方法是检查请求对象,例如...

@csrf_exempt
def process(request):
    if request.META['REMOTE_ADDR'] != '127.0.0.1':
        # Return some error response here.
        # 403 is traditional for access denied, but I prefer sending 404
        # so 'hackers' can't infer the existence of any 'hidden' URLs
        # from the response code
        raise Http404
    # Now do the thing
    ....

...虽然可能有一些内置的装饰器或类似的东西可以为你做这件事。

【讨论】:

啊,我明白了它是如何工作的——我认为它会将 nonce 存储在数据库中,我可以只用它来验证。这肯定回答了这个问题,并且那个装饰器使它工作得很好。但是有一个问题,如何保护它以便只有服务器可以访问它?例如,Django 视图能否仅接受来自给定 IP 的内容? @CallumM 查看更新的答案。如果您有很多这样的方法,可能值得考虑使用自定义中间件来拦截所有请求并检查权限。 啊,太好了,谢谢!这是目前唯一的情况,但这很容易改变 - 非常 WIP 项目。出于同样的原因,我也会为错误的请求提出 404。干杯! :)

以上是关于Pyres 工作人员对我的视图的 Django POST 请求 - CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章

Django - 如何进行视图所需的大型初始化(APIView)

如何不使用 Django 的管理员登录视图?

在 django 中测试自定义管理操作

是否可以将请求数据访问到 django 通用列表视图中?

在我的第一个视图 Django 中如何/出了啥问题

Django 1.6:如何访问视图中的静态文件