use*_*007 3 django django-csrf
和周围的很多人一样,我在使用 CSRF 和 Django 时遇到了很多问题。
这是上下文:
- 我创建了一个 https 网站,用户可以在其中上传文件
- 我使用 Django 1.4.2 创建了这个网站
- 我创建了一个应用程序 *file_manager* 可以做我想要的
- 我是仅通过管理网址使用此应用程序
如果我django.middleware.csrf.CsrfViewMiddleware在MIDDLEWARE_CLASSESmy 中禁用,则settings.py一切正常。
我可以在 Debian Squeeze 下的命令行中使用 cURL 在我的模板上上传文件,该文件命中服务器,没问题。
然而,它似乎并不安全。
所以我启用django.middleware.csrf.CsrfViewMiddleware
它不再起作用。我收到有关 CSRF 验证的各种错误。
我相信我已经消除了通常的嫌疑人(我希望至少
):{% csrf_token %}
- - RequestContext
-CsrfViewMiddleware在settings.py
您会在下面找到该过程中涉及的所有文件(我希望):
视图.py
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import Context, loader, RequestContext
from django.shortcuts import render, get_object_or_404, redirect, render_to_response
from django.core.urlresolvers import reverse
from django.core.context_processors import csrf
from django.views.decorators.csrf import csrf_exempt
from file_manager.models import MyClass
from file_manager.forms import MyClassForm
def index(request):
latest_file_list = MyClass.objects.order_by('-name')[:5]
context = Context({
'latest_file_list': latest_file_list,
})
return render(request, 'file_manager/index.html', context)
def list(request):
# Handle file upload
if request.method == 'POST':
form = MyClassForm(request.POST, request.FILES)
if form.is_valid():
newdoc = MyClass(name='testupl', filefield = request.FILES['docfile'], uploader='fcav')
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('file_manager.views.list'))
else:
form = MyClassForm() # A empty, unbound form
# Load documents for the list page
documents = MyClass.objects.all()
# Render list page with the documents and the form
con = {'documents': documents, 'form': form}
con.update(csrf(request))
return render_to_response(
'list.html',
con,
context_instance=RequestContext(request)
)
Run Code Online (Sandbox Code Playgroud)
列表.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li><a href="{{ document.filefield.url }}">{{ document.filefield.name }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<!-- Upload form. Note enctype attribute! -->
<form action="{% url list %}" method="post" enctype="multipart/form-data">{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
这是我的 curl 请求:
curl --cacert /home/fcav/apache.pem --user admin:password
-e "https://domain.com/admin/" -X POST
-F "docfile=@/home/fcav/Downloads/basket.csv"
https://domain.com/admin/file_manager/myclass/list/
Run Code Online (Sandbox Code Playgroud)
我已经尝试通过尝试在请求中发送 cookie 来尝试 curl 请求的许多变体,但现在我认为我对 cURL 处理上传的方式完全混淆了。
我得到的只是未设置 CSRF Cookie 或 CSRF 验证失败。
如果有人足够了解 cURL 和 Django 以提示我如何在不禁用 CSRF 的情况下尝试在我的网站上上传,我将不胜感激。
问候, 弗洛里安
通过CSRF验证有两种方法:
csrftokenCSRF cookie,其中将包含CSRF 令牌,Django 将使用它来验证请求X-CSRFTokenHTTP 标头传递当您在 中执行请求时curl,您正在向 Django 将使用 CSRF 验证的页面发出请求,但是您没有将 CSRF 令牌传递给它,因此 Django 无法验证请求。
我不知道如何使用 curl,所以请原谅我不知道如何在 curl 中使用,但以下步骤应该可以帮助您解决问题:
1第一步是获取 csrf 令牌:
您可以通过首先使用视图负责GET的 url请求来做到这list一点。这将返回一个 HTML 文档,其中包含{% csrf_token %}返回的内容。您可以解析该段并从那里存储令牌值。
第二种方法是在视图中添加ensure_csrf_cookie 装饰器list。该装饰器将确保该视图将始终csrftoken与请求一起返回一个cookie。然后您仍然需要发出GET请求,但是{% csrf_token %}您可以从返回的 cookie 中获取 csrf 令牌,而不是解析 的结果。
此步骤将为您提供将在下一步中使用的 csrf 令牌的值。
2现在您将拥有 csrf 令牌,在发出POST请求时,您还将传递X-CSRFToken带有您在上一步中获得的令牌值的附加标头。传递令牌将允许 Django 验证请求,从而处理上传的文件。
遵循这些步骤将允许您发出 csrf 有效的请求。对于这种方法,无论请求是使用 HTTP 还是 HTTPS 发出都无关紧要。HTTPS 提供数据完整性、数据保密性的保证并验证服务器的真实性。它不向服务器提供客户端验证,这就是 CSRF 适用于 HTTP 和 HTTPS 的原因。
| 归档时间: |
|
| 查看次数: |
6023 次 |
| 最近记录: |