0

我正在使用 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)

4

1 回答 1

1

我想我看到了问题。

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

问题是您在 Pyres 工人工作中提出的要求......

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

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

假设/tasks/nlp/process/URL 受到保护,只能由服务器访问,那么让process()视图免于 CSRF 检查可能是最简单的......

@csrf_exempt
def process(request):
   ...

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

更新

为确保该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
    ....

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

于 2013-05-01T16:45:38.000 回答