我目前有一个使用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
答案 0 :(得分:2)
这似乎是OS / HW配置错误。
我怀疑有时您的网络出现故障且操作系统(操作系统)需要从硬件时钟获取数据但是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
一些简单的测试:
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
答案 1 :(得分:2)
Apache日志表明一个非常离散的时间步长为5小时,因此这不太可能是通过保留守护进程(如ntp)进行的基础系统时间调整。我猜这几乎肯定与时区设置有关。
如果您使用mod_wsgi以非守护进程模式为您的应用程序提供服务,则可能存在来自环境的进程之间的共享状态。特别是,您应该注意以下链接中的信息:https://code.google.com/p/modwsgi/wiki/ApplicationIssues#Timezone_and_Locale_Settings
正如其他答案中所建议的那样,始终以UTC格式存储时间并仅转换为特定时区的演示文稿是个好主意。
考虑在wsgi守护程序模式下运行您的应用程序。来自mod_wsgi docs
虽然嵌入式模式在技术上可以更好地执行守护进程模式 通常是最安全的选择。
守护进程模式确保您有一个独立的进程处理您的应用程序,不会受到其他wsgi进程的环境污染。例如TZ环境变量变化。
答案 2 :(得分:1)
这可能无法解决您的问题,但值得建议。把它放在评论中看起来不合适。
使用时区感知日期时间对象而不是天真的对象(datetime.datetime.now()
为您提供。)
在处理日期/时间时使用datetime.datetime.utcnow()
而不是.now()
。
所以来自django timezones
import datetime
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
当将request.session['beginSession']
中存储的时间从天真地转换为时区感知对象时,django可能会应用时区。
答案 3 :(得分:0)
日志文件中时间戳的差异通常是因为您的系统时区与Django配置使用的时区不同。如果使用Apache / mod_wsgi的嵌入式模式,您也可能遇到同样在同一台Apache服务器上托管PHP应用程序而PHP使用不同时区的问题。