Django登录/会话不粘滞

sch*_*cki 0 authentication django session login django-allauth

我的网站在生产中启动并运行了一段时间后,我的用户突然登录该网站时遇到了问题。

我已经使用login_required装饰器保护了某些视图/页面,并且我也在使用django admin。当匿名用户访问这些页面中的任何一个时,他将被重定向到登录页面。当该匿名用户添加其凭据时,POST请求成功,并且将其重定向到初始页面。同时,用户将获得一个新的sessionid(如预期的那样)。但是,现在结果变得非常不可靠。当按reload或导航到其他页面(需要登录)时,可能会发生以下两种情况之一:a)识别用户并正确显示该页面b)将用户重定向到登录页面。我已经通过外壳检查了会话的内容,并且那里没有任何变化。

通过负载平衡器和8个应用程序服务器为生产站点提供服务。甚至更陌生:如果我在测试服务器上测试相同的代码(具有相同的设置),那么负载均衡且基本上没有流量,则一切正常。

我在Ubuntu上使用Apache和mod_wsgi在SSL后面的守护进程模式下运行Django 1.6,并且正在使用会话数据库后端。我正在使用django-allauth.account进行帐户管理/登录。我的会话设置如下:

SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_AGE = 60*60*24
SESSION_COOKIE_SECURE = True
Run Code Online (Sandbox Code Playgroud)

更新

为了获得更多调试信息,我创建了以下中间件:

from django.conf import settings

class SessionDebugMiddleware(object):
    def process_response(self, request, response):
        session = request.session
        user = getattr(request, 'user', None)
        if user:
            user=user.id
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        response['X-Meta-Requ'] = '{0},{1},{2},{3}'.format(session_key, session.get('_auth_user_id'), session.get('_auth_user_backend','---'), user)
        return response
Run Code Online (Sandbox Code Playgroud)

如果我按了10次刷新按钮,

  • 8次,我将获得此标头:igv0xshezhdxh50kks9x00r0l67mx0sk,None,---,None
  • 2次,我将获得此标头:X-Meta-Requ:igv0xshezhdxh50kks9x00r0l67mx0sk,330619,django.contrib.auth.backends.ModelBackend,330619

它似乎是随机的,不遵循任何逻辑。

所以我有以下问题/想法?

  1. 无论如何,这可能与负载平衡有关吗?我的理解是,使用数据库会话后端时,Django不需要粘性会话。

  2. 这可能与线程问题有关吗?

  3. 这可能与高负载有关吗?

  4. 这是否与解码问题有关:https : //github.com/django/django/blob/master/django/contrib/sessions/backends/base.py#L83。但是为什么那个解码问题应该不一致。而且我还没有找到任何引用“会话数据已损坏”的日志条目。

任何其他提示都欢迎。

小智 5

万一有人遇到此问题,也可能由SECRET_KEY定义不一致引起。

我在设置文件中生成了我的(错误的决定)。在开发模式下很好,但是一旦WSGI为应用程序提供服务后,就会创建多个实例,每个实例具有不同的密钥。这导致哈希中的混合,并报告损坏的会话。