1

我目前有一个使用 cookie 会话的 django 站点。我注意到会话被随机注销。在调试时,我发现这是由于我的代码中的逻辑查看了会话的年龄。但是,我随后注意到,在没有问题的期间,Apache 时间戳中显示了正确的时间。但是随后 tiemstamp 退回了 5 个小时,导致我的 Django 程序认为会话已过期并将其注销。

下面给大家举个例子,

[Wed Jul 31 16:12:45 2013] [error] DEBUG ok elapsed time 7
[Wed Jul 31 16:12:45 2013] [error] DEBUG ok elapsed time 1
[Wed Jul 31 10:12:46 2013] [error] DEBUG : request.user.is_authenticated()
[Wed Jul 31 10:12:46 2013] [error] DEBUG ok elapsed time 64809
[Wed Jul 31 10:12:46 2013] [error] DEBUG  since begin . elapsedTime.seconds 64809
[Wed Jul 31 10:12:46 2013] [error] DEBUG request.session\\['deginRequest'\\]
[Wed Jul 31 10:12:46 2013] [error] DEBUG ok elapsed time 64801
[Wed Jul 31 10:12:46 2013] [error] DEBUG  since last req . elapsedTime.seconds 64801
[Wed Jul 31 10:12:46 2013] [error] DEBUG request.session\\['lastRequest'\\]
[Wed Jul 31 10:12:47 2013] [error] DEBUG : shouldLogout

这个问题也随机发生。有任何想法吗 ?

这也是我使用的中间件(生成这些日志),

class timeOutMiddleware(object):

    def process_request(self, request):

        shouldLogout = False

        if request.user.is_authenticated():
            print "DEBUG :request.user.is_authenticated()"
            if 'beginSession' in request.session:
                elapsedTime = datetime.datetime.now() - \
                              request.session['beginSession']
                print "DEBUG ok elapsed time",elapsedTime.seconds
                if elapsedTime.seconds > 12*3600:
                    print "DEBUG  since begin . elapsedTime.seconds",elapsedTime.seconds
                    del request.session['beginSession']
                    print "DEBUG  request.session\[\'deginRequest\'\]"

                    shouldLogout = True
            else:
                request.session['beginSession'] = datetime.datetime.now()

            if 'lastRequest' in request.session:
                elapsedTime = datetime.datetime.now() - \
                              request.session['lastRequest']
                print "DEBUG ok elapsed time",elapsedTime.seconds
                if elapsedTime.seconds > 2*3600:
                    print "DEBUG   since last req . elapsedTime.seconds",elapsedTime.seconds
                    del request.session['lastRequest']
                    shouldLogout = True

            request.session['lastRequest'] = datetime.datetime.now()


            username = request.user
            if ####.objects.get(username=username).token:
                print "DEBUG : ####.objects.get(username=username).token"

                try:
                    token = ####.objects.get(username=username).token
                    url = 'https://############/%s' % (token)
                    response = requests.get(url)
                    answer = json.loads(response.text)
                    #print "DEBUG answer",answer
                    if not answer["valid"]:
                        shouldLogout = True
                        print "DEBUG",datetime.now(),"not answer[\"valid\"]"
                except:
                    shouldLogout = True
                    print "DEBUG except"
            else:
                shouldLogout = True
                print "DEBUG else"

            if shouldLogout:
                print "DEBUG : ",datetime.datetime.now(),"shouldLogout"
                logout(request)

        else:
            if 'beginSession' in request.session:
                del request.session['beginSession']
            if 'lastRequest' in request.session:
                del request.session['lastRequest']

        return None
4

4 回答 4

2

Apache 日志表明一个非常离散的时间步长为 5 小时,因此这不太可能是由诸如 ntp 之类的计时守护程序进行的底层系统时间调整。我猜它几乎肯定与时区设置有关。

如果您使用 mod_wsgi 在非守护程序模式下为您的应用程序提供服务,则环境中的进程之间可能存在共享状态。特别是,您应该注意以下链接中的信息:https ://code.google.com/p/modwsgi/wiki/ApplicationIssues#Timezone_and_Locale_Settings

正如其他答案中所建议的那样,始终以 UTC 存储时间并仅转换为特定时区向上表示是一个好主意。

考虑在 wsgi 守护程序模式下运行您的应用程序。来自mod_wsgi 文档

虽然嵌入式模式在技术上性能更好,但守护模式通常是最安全的选择。

守护程序模式确保您有一个独立的进程来处理您的应用程序,而不会受到其他 wsgi 进程的环境污染。例如 TZ 环境变量更改。

于 2013-08-03T01:08:31.603 回答
2

这似乎是操作系统/硬件配置错误。

我怀疑有时您的网络出现故障,操作系统(操作系统)需要从硬件时钟获取数据,但 ntp。

您应该确保BIOS 时钟 UTC 配置与/etc/default/rcS参数匹配:

# assume that the BIOS clock is set to UTC time (recommended)
UTC=no

此外,请确保您的时区配置正确:

root@egg-v3:/etc# cat /etc/timezone 
Europe/Barcelona

一些简单的测试:

  • 启动没有ntp的机器。如果系统数据不正确,请尝试更改UTC参数。
  • hwclock命令:

样本:

root@egg-v3:/etc# hwclock 
Fri 02 Aug 2013 04:30:54 PM CEST  -0.609670 seconds
root@egg-v3:/etc# date
Fri Aug  2 14:30:55 CEST 2013
于 2013-08-02T12:26:53.003 回答
1

这可能无法解决您的问题,但值得建议。并将其放在评论中看起来不合适。


使用时区感知日期时间对象而不是天真的对象(datetime.datetime.now()给你。)

使用datetime.datetime.utcnow()而不是.now()在使用日期/时间时使用。

所以从django 时区

import datetime
from django.utils.timezone import utc

now = datetime.datetime.utcnow().replace(tzinfo=utc)

当 django 将存储的时间request.session['beginSession']从天真转换为时区感知对象时,可能会出现应用时区错误的情况。

于 2013-08-02T08:40:31.747 回答
0

日志文件中时间戳的差异通常是因为您的系统时区与 Django 配置使用的时区不同。如果使用 Apache/mod_wsgi 的嵌入式模式,您还可能在同一 Apache 服务器上托管 PHP 应用程序并且 PHP 使用不同的时区时会遇到问题。

于 2013-08-04T07:13:42.477 回答