python - 注销后Django重新加载并重新登录

标签 python django persona

Django v1.7

我一直在努力this book (顺便说一句,这太棒了),我以为我一切正常。所有测试(功能和单元),但由于某种原因,每次我点击注销按钮时,我都会立即重新登录。我正在使用自定义身份验证后端(在书),它使用 Mozilla Persona,如书中所述(链接中的章节)。

我看过一些类似的帖子,但没有一个解决方案有帮助。

行为:

  1. 使用错误的凭据登录将不断刷新页面, 似乎每次都会查询 Persona (Persona 错误: 角色说不。 Json was: {'status': 'failure', 'reason': 'audiencemismatch:domainmismatch'} --我无意中发现 通过访问 127.0.0.1:8000 而不是 localhost:8000*)。我 不知道是否每次都查询Persona或者消息是否 每次页面刷新后保留。
  2. 初始登录似乎工作正常。角色弹出窗口会出现,并在关闭和重新加载页面之前完成这些步骤。

  3. 注销后,页面将刷新,发送帖子信息并重新登录: [06/11/2015 21:25:20]“获取/帐户/注销HTTP/1.1”302 0 [2015 年 11 月 6 日 21:25:20]“获取/HTTP/1.1”200 795 [2015 年 11 月 6 日 21:25:21] “POST/accounts/login HTTP/1.1” 200 2 注销被重定向回根页面“/”。

  4. 通过重新启动服务器和 Web 浏览器,此行为将持续存在。如果我停止服务器并关闭浏览器并重新打开两者(再次输入网址),则该页面已登录。

  5. 这种行为在不同的 git 分支中也持续存在。我不确定它何时开始(因为测试仍然通过),但我知道它以前有效。我检查的每个分支都有同样的问题,这让我认为这与缓存或安装有关。

  6. 通过删除所有 __pycache__、迁移和数据库本身,该行为也会持续存在。

  7. 清除缓存后,该行为仍然存在。 (编辑/更新:我仍在写这篇文章,所以从技术上讲这不是更新...我之前只清空了“今天”(Firefox) 的缓存,这没有效果;但是,我刚刚清除了所有内容,似乎已经解决了问题。我需要做更多测试;确定后我会更新。)

*我确实知道 Persona 说要使用 localhost 上的 IP,但这似乎没有什么区别。

这是一个最小的工作示例:

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>

accounts/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('/')

url.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'),
)

accounts/urls.py(注意:我使用的是 native 注销 - 这两种方法都不起作用)

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

编辑/更新再次,当我写这篇文章时。看来这个问题已经解决了here 。我有这本书的实体副本,但是使用在线副本回顾并验证所有内容,我刚刚找到了指向此代码的链接。我会将其保留,以防其他人遇到此问题...或者,如果我能找到指向相同解决方案的相同问题,我将删除它。

最佳答案

从上面:

It would appear that this problem has already been solved here 。我有这本书的实体副本,但是使用在线副本回顾并验证所有内容,我刚刚找到了指向此代码的链接。我会保留这个,以防万一其他人遇到这个问题......或者,如果我能找到指向相同解决方案的相同问题,我会将其删除。

关于python - 注销后Django重新加载并重新登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33576577/

相关文章:

javascript - Mozilla Persona 签名数据字符串

python - 重启死亡进程的方法

python - 如何在Redis列表中有效存储16位整数

python - 如何从 [0,1] 生成随机数?

python - Django 表单 - 使用数据库中的变量

当从 jQuery load() 调用 URL 时,javascript 未从 django 模板加载

python - Django:将变量从 get_context_data() 传递到 post()