Django POST请求从我的观点从Pyres工人 - CSRF令牌

问题描述:

我正在使用Pyres工作人员做一些处理数据用户在窗体中输入。他们的处理是通过我的表单上的视图完成的,我通过该表单进行POST请求,其中包含要处理的数据以及用户的CSRF中间件令牌。我的问题是,这显然是不够的,因为Django仍然拒绝了我的要求,禁止403。Django POST请求从我的观点从Pyres工人 - CSRF令牌

相关代码:

表单处理程序:

 
def handler(request): 
    if(request.method == "POST"): 
     if(request.POST.__contains__("taskdata")): 
      #valid post of the form 
      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(TaskData, t.id) 

      return HttpResponse(t.id) 


     else: 
      #invalid post of the form 
      raise Http404 
    else: 
     raise Http404 

柴堆工人的工作:

 
    @staticmethod 
    def perform(taskData_id): 
     #Get the taskData from this id, test it for tasky stuff 
     task_data = TaskData.objects.get(pk=taskData_id) 

     post_data = [('id',task_data.id),('data',task_data.data), ('csrfmiddlewaretoken',task_data.token)]  # a sequence of two element tuples 
     result = urllib2.urlopen('http://127.0.0.1:8000/tasks/nlp/process/', urllib.urlencode(post_data)) 
     content = result.read() 
     return 

查看由该作业发布到:

 
def process(request): 
    if(request.method == "POST"): 
     return HttpResponse("HEY, it works!") 
     if(request.POST.__contains__("data") and request.POST.__contains__("id")): 
      #valid post to the form by the model 
      #taskdata = escape(request.POST.get("taskdata","")) 
      #data = get_times(taskdata) 
      return HttpResponse("Hey from process!") 
      #return HttpResponse(json.dumps(data)) 

     else: 
      #invalid post of the form 
      raise Http404 
    else: 
     raise Http404 

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

不幸的是,张贴令牌似乎不够。

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

(建议标签:pyres)

+0

什么是handler()函数? Django视图,中间件功能还是其他? – Aya 2013-05-01 16:27:17

+0

对不起,handler()是一个Django视图。它位于通过表单发布到的URL上。process()也是一个视图,同样一个可预测的URL(我的工作者perform()方法在那里发布)。 perform()方法是Pyres使用的模型类上的方法。 – 2013-05-01 16:32:00

我想我看到了问题。

Django's CSRF protection works的方式是生成一个随机数,然后将Cookie设置为随机数值,并确保csrfmiddlewaretoken POST值与该cookie的值匹配。其基本原理是它使它成为无状态的系统,没有任何持久的会话数据。

的问题是,您在柴堆工人工作做出的请求......

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工作任务。

更新

为了保证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 
    .... 

...虽然可能会有一些内置的装饰器或者其他的为你做这个。

+0

啊,我看到它是如何工作的 - 我认为它将存储在数据库中的随机数,我可以用它来验证。这肯定回答了这个问题,而装饰者使它很好地工作。但有一个问题,如何保护它,只有服务器可以访问它?例如,Django的视图只能接受来自给定的IP吗? – 2013-05-01 16:50:29

+0

@CallumM查看更新的答案。如果你有很多这样的方法,那么使用自定义中间件拦截所有请求并检查权限可能是值得的。 – Aya 2013-05-01 16:58:24

+0

啊,太好了,谢谢!这是目前唯一的情况,但这很容易改变 - 非常WIP项目。出于同样的原因,我也为不良请求提出404。 干杯! :) – 2013-05-01 17:15:25