最近,我在基于 Django 的网站上开始遇到一个问题,网站正常运行几天后,登录将失败,并且没有向用户报告任何错误。已经登录的 session 继续正常工作,但不会发生新的登录。
相关信息:
我正在使用普通的
django.contrib.auth
身份验证工具我通过
django.db.backends.postgresql_psycopg2
后端将 PostgreSQL 用于数据库我在 OSX 10.6.7 上运行 Python 2.6.1 和 Django 1.3
Django 在 nginx 后面以 FastCGI 模式运行
我的直觉是,与数据库的连接/套接字在某个时候出现了故障,因为如果我杀死 Django 并重新启动它,一切都会再次正常工作(即数据库本身绝对没有过载并且可以可以使用 psql
命令行工具访问。
不幸的是,日志中没有关于错误的任何内容(好吧,至少没有通过正常的 Python logging
模块发出任何内容,这就是我捕获所有日志的方式)并且没有错误报告给网络浏览器。客户所看到的只是他们再次被发送回登录页面,就好像他们刚刚刷新了浏览器一样。
非常感谢任何帮助。
不确定是否相关,但我的中间件类是:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
更新
查看 nginx 访问日志后,我可以看到登录实际上短暂地工作然后突然不起作用:
"POST /accounts/login/ HTTP/1.1" 302 5 "https://myapp.com/accounts/login/?next=/orders"
"GET /orders HTTP/1.1" 301 185 "-"
"GET /orders HTTP/1.1" 302 5 "-"
"GET /accounts/login/?next=/orders HTTP/1.1" 301 185 "-"
"GET /accounts/login/?next=/orders HTTP/1.1" 200 1297 "-"
如您所见,登录有效,客户端被重定向到“下一个”URL (/orders),但随后第三行重定向 (302) 客户端返回到登录页面,大概是因为 @login_required装饰器(应用于/orders Controller )确定他们并未真正登录。
为了比较,这是一个成功的登录序列:
"POST /accounts/login/ HTTP/1.1" 302 5 "https://myapp.com/accounts/login/?next=/orders"
"GET /orders HTTP/1.1" 301 185 "-"
"GET /orders HTTP/1.1" 200 59364 "-"
以及使用错误密码登录(POST 返回 200 而不是 302):
"POST /accounts/login/ HTTP/1.1" 200 1426 "https://myapp.com/accounts/login/?next=/orders"
正常登录和损坏登录之间的区别在于,客户端获得/orders 的 200 OK 而不是返回登录页面的 302。我不知道 auth 中间件如何允许登录,然后立即将用户踢出。这里是否存在可能的竞争条件,登录 Controller 无法及时将登录状态持久保存到数据库中,以便/orders Controller 看到它并允许用户保持登录状态?
此外 - 我注意到不一定需要重新启动 Django 才能解决问题 - 有时服务器会奇迹般地开始让客户端再次登录。
最佳答案
听起来您的 Web 服务器正在使用持久连接并且快用完了。当您无法登录时,pg 日志会说什么?
关于Django 登录尝试有时会默默地失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6227197/