2013-05-01 94 views
0

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

回答

1

我想我看到了問題。

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