Django: токен CSRF отсутствует или неверен при выполнении PUT в C # .net - PullRequest
0 голосов
/ 05 сентября 2018

Я создаю плагин для определенного приложения в c #, который должен взаимодействовать с интерфейсом отдыха Django. Как вы знаете, Django использует токены CSRF для дополнительной безопасности.

У меня проблема при выполнении вызова POST / PUT для Django. Вызов всегда будет возвращать «CSRF Failed: токен CSRF отсутствует или неверен». Я протестировал вызов в браузере (веб-интерфейс также может редактировать данные и будет вызывать тот же запрос PUT), и, к моему удивлению, в заголовке X-CSRFToken используется другое значение токена csrf, чем значение, сохраненное в cookie , Должен ли заголовок X-CSRFToken использовать только что созданный токен? Значение X-CSRFToken никогда не используется снова после этого вызова (старое значение csrftoken все еще используется для всех последующих вызовов ...).

Очевидно, я также читал документы Django относительно токенов csrf. Хотя я думаю, что понимаю, как это работает, я не понимаю, почему новый токен используется для POST / PUT. Есть много примеров, которые не имеют смысла для использования в моем плагине C #.

Что я делаю, прежде чем делать PUT:

  • Получите токен CSRF, запросив страницу входа, содержащую в своем теле csrfmiddlewaretoken.
  • Сохранить файл cookie "csrftoken" с токеном в качестве значения (К сожалению, файл cookie не сохраняется автоматически)
  • Войти в систему (POST), используя учетные данные (csrfmiddlewaretoken = {token} также передается в качестве параметра)

После выполнения вышеописанного все вызовы GET работают отлично. Проблема возникает, когда я пытаюсь сделать POST или PUT. Это мой код PUT, игнорирующий генерацию json и url, поскольку это не проблема:

// The _csrftoken used here, is the one I fetch at the beginning
Client().DefaultRequestHeaders.Add("X-CSRFToken", _csrftoken);

// The content is json
var response = Client().PutAsync(url, content).GetAwaiter().GetResult();

// The returned content is: {"detail":"CSRF Failed: CSRF token missing or incorrect."}"
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

// 403 is returned
if (response.IsSuccessStatusCode) { ... }

Код выше выполнен со следующим состоянием:

  • Пользователь вошел в систему (сессионный cookie доступен)
  • токен csrf доступен при входе в систему (также доступен файл cookie csrftoken)

Что я пытался решить проблему:

  • Передать csrfmiddlewaretoken = {token} в качестве параметра
  • сохранить файл cookie X-CSRFToken
  • Использование X-CSRFToken, который я скопировал из PUT, выполненного в веб-интерфейсе
  • Попытка HttpWebRequest вместо PutAsync
  • Реплицируйте PUT из веб-интерфейса, скопировав все заголовки / параметры / файлы cookie из PUT, выполненного в веб-интерфейсе
  • ...

Может кто-нибудь помочь мне понять, что я делаю неправильно?

Большое спасибо за любую помощь, которую вы можете мне оказать.

1 Ответ

0 голосов
/ 12 октября 2018

Таким образом, проблема здесь заключалась в том, что мы пытались использовать API вне контекста просмотра веб-страниц и исключительно как API для выполнения вызовов GET / POST / ... Это не работает при использовании токенов CSRF, поскольку эти токены передаются при просмотре в виде файлов cookie и метаданных на html-странице.

Таким образом, использование API с токенами CSRF работает только в том случае, если API используется в контексте просмотра. Если вы хотите использовать API вне этого контекста, вам нужно использовать другую форму аутентификации, например OAuth2.

Для того, чтобы это работало без контекста просмотра, вам нужно выбрать html-страницу для каждого POST / PUT / DELETE, чтобы получить новый токен CSRF, который вы должны передать вместе с вызовом. Очевидно, это приносит много накладных расходов, и вы не хотите работать с API.

Я попросил разработчика API предоставить аутентификацию OAuth2.

...