我正在使用Pyres工作人员对用户在表单中输入的数据进行一些处理。他们的处理是通过我的表单上的视图完成的,我向POST发出请求,其中包括要处理的数据和用户的CSRF中间件令牌。我的问题是,这显然是不够的,因为Django仍然拒绝我的403禁止请求。
相关代码:
表单处理程序:
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
Pyres工作人员:
@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 :(得分: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工作者。
<强>更新强>
要确保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
....
...虽然可能有一些内置的装饰器或者其他一些为你做这件事。