Перезагрузите Django и войдите снова после выхода

Джанго v1.7

Я работал над этой книгой (что фантастически, кстати), и я думал, что у меня все работает. Все тесты (функциональные и единичные), но по какой-то причине каждый раз, когда я нажимаю logout Кнопка, я сразу же вошел обратно. Я использую пользовательский сервер аутентификации (тот, который приведен в книге), который использует Mozilla Persona, как описано в книге (глава в ссылке).

Я видел несколько похожих постов, но ни одно из решений не помогло.

Поведение:

  1. Вход с неверными учетными данными будет постоянно обновлять страницу, которая каждый раз запрашивает Persona (ошибка Persona: Persona says no. Json was: {'status': 'failure', 'reason': 'audience mismatch: domain mismatch'} - Я случайно обнаружил это, посетив 127.0.0.1:8000 вместо localhost:8000 *). Я не знаю, запрашивается ли Persona каждый раз или сообщение сохраняется после каждого обновления страницы.
  2. Начальный логин, кажется, работает правильно. Появляется всплывающее окно с персоной, которое проходит через все шаги перед закрытием и перезагрузкой страницы.

  3. После выхода из системы страница обновится, отправив информацию о записи и войдя обратно: [06/Nov/2015 21:25:20] "GET /accounts/logout HTTP/1.1" 302 0 [06/Nov/2015 21:25:20] "GET / HTTP/1.1" 200 795 [06/Nov/2015 21:25:21] "POST /accounts/login HTTP/1.1" 200 2 Выход перенаправляется обратно на корневую страницу "/".

  4. Такое поведение сохраняется после перезапуска сервера и веб-браузера. Если я остановлю сервер, закрою браузер и снова открою оба (снова введя веб-адрес), страница уже будет авторизована.

  5. Это поведение также сохраняется через различные ветви git. Я не уверен, когда это началось (потому что тесты все еще проходят), но я знаю, что это работало ранее. Каждая ветка, которую я проверял, имеет одну и ту же проблему, из-за которой я думаю, что это связано с кешем или установкой.

  6. Поведение также сохраняется путем удаления всех __pycache__, миграций и самой базы данных.

  7. Поведение сохраняется за счет очистки кэша. (РЕДАКТИРОВАТЬ / ОБНОВИТЬ: я все еще пишу это, так что это технически не обновление... Я ранее очищал кеш только для "Сегодня" (Firefox), который не имел никакого эффекта; однако я просто очистил все, и это кажется, решил проблему. Мне нужно больше тестировать, я буду обновлять, когда я уверен.)

* Я знаю, что Персона говорит, чтобы использовать IP над localhost, но это, кажется, не имеет значения.

Вот минимальный рабочий пример:

placeholder.html (ПРИМЕЧАНИЕ: я помещаю скрипты в тело.

{% load staticfiles %}

<html>
<head>
    <title>placeholder</title>
</head>

<body>
    {% if user.email %}
        <h3>User: {{ user.email }}</h3>
        <div class="item">
            Logged in as <b>{{ user.email }}</b>
        </div>
        <div class="item">
            <a class="ui button" id="id_logout"
                href="{% url 'logout' %}">Log out</a>
        </div>
    {% else %}
        <div class="item">
            <a class="ui button" id="id_login" href="#">Sign in</a>
        </div>
    {% endif %}

    <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    <script src="https://login.persona.org/include.js"></script>

    <script>
    var initialize = function(navigator, user, token, urls) {
      console.log('called initialize');
      $('#id_login').on('click', function() {
        navigator.id.request();
      });
      navigator.id.watch({
        loggedInUser: user,
        onlogin: function(assertion) {
          $.post(
            urls.login,
            {'assertion': assertion, 'csrfmiddlewaretoken': token}
          )
            .done(function() { window.location.reload(); })
            .fail(function() { navigator.id.logout(); });
        },
        onlogout: function() {}
      });
    };

    window.MyModule = window.MyModule || {
      Accounts: {
        initialize: initialize
      }
    };
    </script>

    <script>
    /*global $, MyModule, navigator */
    $(document).ready(function () {
        var user = "{{ user.email }}" || null;
        var token = "{{ csrf_token }}";
        var urls = {
            login: "{% url 'persona_login' %}",
            logout: "TODO",
        };
        MyModule.Accounts.initialize(navigator, user, token, urls);
    });
</script>

</body>
</html>

account /views.py (ПРИМЕЧАНИЕ: я использовал Django, родной auth.logout, который вы увидите в urls.py)

from django.contrib.auth import authenticate, login
from django.contrib.auth import logout as auth_logout
from django.http import HttpResponse
from django.shortcuts import redirect

def persona_login(request):
    user = authenticate(assertion=request.POST['assertion'])
    if user is not None:
        login(request, user)
    return HttpResponse('OK')


def logout(request, next_page):
    auth_logout(request)
    return redirect('/')

urls.py

from django.conf.urls import patterns, include, url
#from django.contrib import admin

urlpatterns = patterns(
    '',
    # url(r'^admin/', include(admin.site.urls)),

    url(r'^accounts/', include('apps.accounts.urls')),

    url(r'^$', 'apps.projects.views.placeholder_view',
        name='placeholder'),
)

account /urls.py (ПРИМЕЧАНИЕ: я использовал собственный выход из системы - ни один из методов не работает)

from django.conf.urls import patterns, url
# from django.contrib.auth.views import logout

urlpatterns = patterns(
    '',
    url(r'^login$', 'remsci.apps.accounts.views.persona_login',
        name='persona_login'),
    # url(r'^logout$', logout,
    #     {'next_page': '/'}, name='logout'),
    url(r'^logout$', 'remsci.apps.accounts.views.logout',
        {'next_page': '/'}, name='logout'),

authentication.py (ПРИМЕЧАНИЕ: это прямо из книги)

import requests

from django.conf import settings
from django.contrib.auth import get_user_model

User = get_user_model()

PERSONA_VERIFY_URL = 'https://verifier.login.persona.org/verify'

import logging
log = logging.getLogger(__name__)

class PersonaAuthenticationBackend(object):

    def authenticate(self, assertion):
        response = requests.post(
            PERSONA_VERIFY_URL,
            data={'assertion': assertion, 'audience': settings.DOMAIN}
        )

        if response.ok and response.json()['status'] == 'okay':
            email = response.json()['email']
            try:
                return User.objects.get(email=email)
            except User.DoesNotExist:
                return User.objects.create(email=email)
        else:
            log.warning(
                'Persona says no. Json was: {}'.format(response.json()))

    def get_user(self, email):
        try:
            return User.objects.get(email=email)
        except User.DoesNotExist:
            return None

РЕДАКТИРОВАТЬ / ОБНОВИТЬ Снова, пока я писал это. Казалось бы, эта проблема здесь уже решена. У меня есть физическая копия книги, но, вернувшись назад и проверив все с помощью онлайн-копии, я просто нашел ссылку, указывающую на этот код. Я оставлю это на всякий случай, если у кого-то еще возникнет эта проблема... или я устраню ее, если смогу найти ту же проблему, указывающую на то же решение.

1 ответ

Решение

Сверху:

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

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