Файл cookie CSRF не установлен или ошибка проверки CSRF для загрузки по протоколу https на веб-сайте django

Джанго-CSRF Джанго

Как и многие люди, у меня было много проблем с использованием CSRF и Django.

Вот контекст:
- Я создал веб-сайт https, где пользователь может загружать файлы
- Я использовал Django 1.4.2 для создания этого сайта
- Я создал приложение * file_manager *, которое делает то, что я хочу
- Я использую только это приложение через URL-адреса администратора

Если я отключу django.middleware.csrf.CsrfViewMiddleware в MIDDLEWARE_CLASSES из моего settings.py, все работает просто отлично.
Я могу загрузить файл на моем шаблоне с помощью cURL в командной строке под Debian Squeeze, файл попадает на сервер, нет проблем.
Тем не менее, кажется, что это не безопасно.

Итак, я включил django.middleware.csrf.CsrfViewMiddleware Это больше не работает. Я получаю все виды ошибок, касающихся проверки CSRF.

Я считаю, что я устранил обычных подозреваемых (я надеюсь, по крайней мере):
- {% csrf_token %}
- RequestContext
- CsrfViewMiddleware в settings.py

Ниже вы найдете все файлы (я надеюсь), участвующие в процессе:

views.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)
    )

list.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>

И вот моя просьба:

    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/

Я пробовал много вариантов запроса curl, пытаясь отправить cookie-файл в запросе, но теперь я думаю, что мое мнение полностью запутано в том, как cURL обрабатывает загрузку.

Все, что я получаю, это файл cookie CSRF не установлен или ошибка проверки CSRF.

Если кто-нибудь знает cURL и Django достаточно, чтобы дать мне подсказку о том, как я могу попытаться загрузить их на свой сайт без отключения CSRF, я был бы очень признателен.

С уважением, Флориан

2 ответа

Решение

Итак... я сделал это...
Прошло много тестов, но мне наконец удалось...
Похоже, мне нужно было отправить через cURL:
- сертификат с сервера
- заголовок реферера с именем домена
- файл cookie csrftoken с его значением
- дополнительный заголовок со значением токена csrf
- файл, который я хочу загрузить

Что-то вроде этого:

curl --cacert /path/to/cert/apache.pem -e "https://domain.com" --cookie "csrftoken=[value]" -H "X-CSRFToken: [value]" -X POST -F "docfile=@/path/to/myfile/file.csv" https://domain.com/admin/list/

Есть несколько методов прохождения проверки CSRF:

  • Проходить csrftoken Файл cookie CSRF, который будет содержать токен CSRF, который Django будет использовать для проверки запроса
  • Передайте токен CSRF как X-CSRFToken Заголовок HTTP

Когда вы делаете свой запрос в curl, вы делаете запрос к странице, которую Django будет проверять с помощью CSRF, однако вы не передаете ей токен CSRF, так что Django не может проверить запрос.

Я не знаю, как использовать curl, поэтому, пожалуйста, прости меня, что я не знаю, как сделать это в curl, но следующие шаги должны помочь тебе в решении проблемы:

1 Первый шаг - получить токен csrf:

Вы можете сделать это, предварительно запросив GET URL, который list мнение несет ответственность за. Это вернет HTML-документ, который будет содержать содержание того, что {% csrf_token %} вернулся. Вы можете проанализировать этот сегмент и сохранить значение токена оттуда.

Второй способ - добавить ensure_csrf_cookie декоратор к list Посмотреть. Этот декоратор позаботится о том, чтобы представление всегда возвращало csrftoken печенье с просьбой. Тогда вам еще нужно сделать GET запрос, однако вместо анализа результата {% csrf_token %}, вы можете просто получить токен csrf из возвращенного файла cookie.

Этот шаг предоставит вам значение токена csrf, который вы будете использовать на следующем шаге.

2 Теперь, когда у вас будет токен csrf, при создании POST запрос, вы также пройдете дополнительный X-CSRFToken заголовок со значением токена, который вы получили на предыдущем шаге. Передача токена позволит Django подтвердить запрос и, следовательно, обработать загруженный файл.


Выполнение этих шагов позволит вам сделать csrf-действительные запросы. Пожалуйста, для этого подхода не имеет значения, если запрос сделан с использованием HTTP или HTTPS. HTTPS обеспечивает гарантию целостности данных, секретности данных и проверяет подлинность сервера. Он не обеспечивает проверку клиента на сервере, поэтому CSRF применим как для HTTP, так и для HTTPS.

Другие вопросы по тегам