Django Forbidden 403 Ошибка «CSRF-токен отсутствует или неверный» при попытке входа в систему, когда вы уже вошли в систему - PullRequest
0 голосов
/ 13 июня 2018

Итак, я использую все встроенное в Django, у меня нет собственного представления входа в систему.


Сначала я опишу, как создается сценарий, который вызывает эту ошибку:

Итак, кто-то вошел в систему и открыл несколько вкладок, а затем вышел из системы.В конце концов, другие вкладки будут перенаправлены на страницу аккаунтов / входа либо сами, либо обновлены, либо нажата ссылка, на самом деле не имеет значения, как.Дело в том, что у этого человека теперь есть несколько вкладок, которые все находятся на экране учетных записей / входа в систему, и никто не аутентифицирован / не вошел в систему.

Таким образом, этот человек успешно входит в систему на одной из вкладок.Затем они переходят на одну из других вкладок, которые по-прежнему находятся на странице учетных записей / входа в систему (даже если сеанс уже создан).

Если этот человек затем пытается войти в систему как зарегистрированный пользователь,или действительно кого-либо, фактически, даже если имя пользователя и пароль пусты и они просто нажимают кнопку входа в систему, выдается 403 Error CSRF token missing or incorrect.

(надеюсь, это имеет смысл)

В любом случае, как я могу это исправить?

И это мой HTML-шаблон, если это поможет:

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}
  <div class='panel panel-primary' style='margin: 0 auto; max-width: 360px;'>
    <div class='panel-heading'>
      <h3 class='panel-title'>Login</h3>
    </div>
    <div class='panel-body'>
      <form action='{% url 'login' %}' novalidate='novalidate' role='form' method='post'>
        {% csrf_token %}
        {{ form|crispy }}
        <input type='hidden' name='next' value='{{ next }}' />
        <div class='form-group' style='margin-bottom: 0;'>
          <p>
            <small>
              By using this site, you agree to our
              <a href='{% url 'privacy-policy' %}'>privacy policy</a>
              and
              <a href="{% url 'terms-of-use' %}">terms of use</a>.
            </small>
          </p>
          <button class='btn btn-primary' type='submit'>Login</button>
        </div>
      </form>
    </div>
  </div>
{% endblock %}

Редактировать:

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

Я просто хочу, чтобы пользователи никогда не сталкивались с ошибками при использовании сайта (конечно, если не вводить что-либо непосредственно в строку поиска).Одна идея может заключаться в том, что при нажатии входа в систему он обновляет токен csrf так же, как при обновлении страницы, возможно ли это и хорошая идея?

Ответы [ 2 ]

0 голосов
/ 20 июня 2018

Что ж, похоже, я нашел решение, которое точно не решает ошибку напрямую, но позволяет избежать ситуации, когда ошибка может произойти.Поведение немного отличается, но для меня оно работает очень хорошо, и я предполагаю, что в большинстве случаев оно будет таким же, как и у других.

Итак, во-первых, я перенаправляю пользователя со страницы входа, когда пользовательЯ уже выполнил вход в систему. Я делаю это, создавая свое собственное представление для входа в систему:

class LoginView(LoginView):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            return HttpResponseRedirect(request.GET.get("next") or "/")
        else:
            return super().dispatch(request, *args, **kwargs)

Во-вторых, я сделал это так, чтобы каждый раз, когда окно становилось «сфокусированным» (т.е. вы переходили на вкладку), простой запрос ajaxотправлено, чтобы проверить, аутентифицирован ли пользователь, если это так, окно будет перезагружено, таким образом, перенеся его на правильную страницу.

Для этого я добавил этот javascript на страницу login.html:

{% block extrascripts %}
  {{ block.super }}
  <script>
      "use strict";

      window.onfocus = function () {
        $.ajax({
          url: "/accounts/status/",
          success: function(result, status, xhr) {
            if (result.is_authenticated) {
              window.location.reload();
            }
          }
        });
      };
  </script>
{% endblock %}

И добавил это представление:

@method_decorator(csrf_exempt, name="get")
class StatusView(View):
    def get(self, request, *args, **kwargs):
        return JsonResponse({"is_authenticated": request.user.is_authenticated})

И я, конечно, тоже обновил URL.


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

0 голосов
/ 13 июня 2018

это произойдет, потому что, из соображений безопасности, значение секрета изменяется каждый раз, когда пользователь входит в систему.

  • В каждой форме Django у вас есть скрытый ввод, называемый «CSRF-токен»или {% csrf_token %}.Это значение генерируется случайным образом и уникальным образом во время отображения формы и будет сравниваться после выполнения запроса.Таким образом, запрос может быть отправлен только из браузера авторизованного пользователя.Нет никакого способа (о котором я знаю), что злоумышленник может получить этот токен и выполнить вредоносный запрос, который может быть принят бэкэндом Django.

Для всех входящих запросов, которые не используют HTTPGET, HEAD, OPTIONS или TRACE, файл cookie CSRF должен присутствовать, а поле 'csrfmiddlewaretoken' должно присутствовать и быть правильным.Если это не так, пользователь получит ошибку 403.При проверке значения поля 'csrfmiddlewaretoken' сравнивается только секрет, а не полный токен, с секретом в значении cookie.Это позволяет использовать постоянно меняющиеся токены.Хотя каждый запрос может использовать свой собственный токен, секрет остается общим для всех.Эта проверка выполняется CsrfViewMiddleware.

для получения более подробной информации нажмите здесь

...