Django 管理后台认证失败

1 投票
3 回答
1986 浏览
提问于 2025-04-15 18:44

第一次点击“登录”按钮时,登录Django后台失败,但如果点击“返回”再点击一次“登录”,就能成功登录。

我在这里用zc.buildout部署Django应用,设置和这里描述的类似 http://www.meppum.com/2009/jan/17/installing-django-ubuntu-intrepid/。Nginx(监听127.0.0.1:8003)在Apache(监听127.0.0.1:8001)之后运行,两个服务器的配置在帖子最后提供。我是通过127.0.0.1:8003/访问我的Django应用。

所以,访问127.0.0.1:8003/admin/会打开Django后台登录表单。1)输入用户名和密码,点击“登录”后,会重定向到(出于某种未知原因?)127.0.0.1/admin,因此什么也得不到,因为80端口没有服务器在监听。

HTTP跟踪(在点击登录后: http://127.0.0.1:8003/admin/

POST /admin/ HTTP/1.1
Host: 127.0.0.1:8003
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1:8003/admin/
Cookie: JSESSIONID=0D287C17FBA82223AB7D5884EA534967; sessionid=c65c7af8ebde9e6bdf9c739a731d376b
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
username=to&password=password&this_is_the_login_form=1

HTTP/1.x 302 FOUND
Server: nginx/0.8.29
Date: Mon, 01 Feb 2010 10:27:44 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Expires: Mon, 01 Feb 2010 10:27:44 GMT
Vary: Cookie
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Cache-Control: max-age=0
Set-Cookie: sessionid=9db437da69c359136786696f90ba89f2; expires=Mon, 15-Feb-2010 10:27:44 GMT; Max-Age=1209600; Path=/
Last-Modified: Mon, 01 Feb 2010 10:27:44 GMT
Location: http://127.0.0.1/admin/
Content-Length: 0

2)点击浏览器的“返回”,然后再次点击“登录”按钮(或者点击浏览器的“返回”和“刷新”)就能成功登录。HTTP跟踪:

POST /admin/ HTTP/1.1
Host: 127.0.0.1:8003
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1:8003/admin/
Cookie: JSESSIONID=0D287C17FBA82223AB7D5884EA534967; sessionid=9db437da69c359136786696f90ba89f2
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
username=to&password=password&this_is_the_login_form=1

HTTP/1.x 200 OK
Server: nginx/0.8.29
Date: Mon, 01 Feb 2010 10:52:02 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Mon, 01 Feb 2010 10:52:02 GMT
Vary: Cookie
Etag: "3355a46fb32d7cb6ab21262c359d9eec"
Cache-Control: max-age=0
Last-Modified: Mon, 01 Feb 2010 10:52:02 GMT

看起来这可能是个与cookie有关的问题,但我猜问题的根源也可能在于Apache和/或Nginx的配置。

有没有什么办法能让后台登录表单立即工作?

谢谢!

附言:配置:

Apache虚拟主机配置:

<VirtualHost *:8001>

    <Directory /home/toinbis/Desktop/programming/project/runtime/
htdocs/django_wsgi/>
        Order deny,allow
        Allow from all
    </Directory>

    WSGIDaemonProcess tsd user=www-data group=www-data threads=25
    WSGIProcessGroup tsd

    WSGIScriptAlias / /home/toinbis/Desktop/programming/project/
runtime/htdocs/django_wsgi/djproject.wsgi

    LogLevel warn
    ErrorLog  /home/toinbis/Desktop/programming/project/runtime/logs/
apache_tsd_error.log
    CustomLog /home/toinbis/Desktop/programming/project/runtime/logs/
apache_tsd_access.log combined

    ServerName localhost
</VirtualHost>

Nginx配置:

daemon off;
#user www-data;
worker_processes  2;

error_log  /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_general_error.log;
pid        /home/toinbis/Desktop/programming/project/runtime/var/pids/
nginx.pid;

events {
    worker_connections  1024;
    #server_names_hash_bucket_size: 128;

}

http {
    include       /home/toinbis/Desktop/programming/project/runtime/
etc/nginx_conf/mime.types;
    default_type  application/octet-stream;

    access_log  /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_access.log;
    error_log   /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_error.log;

    sendfile        on;
    tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  2;
    tcp_nodelay        on;

    server_names_hash_bucket_size 128;
    #server_name_hashes 128;
    gzip  on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)"; #iš ubuntu
    gzip_types text/plain text/css application/x-javascript text/xml
application/xml application/xml+rss text/javascript;

upstream backend {
  server 127.0.0.1:8001;

}

server {
            listen   8003;
            server_name localhost;

            error_log /home/toinbis/Desktop/programming/project/
runtime/logs/project_nginx_error.log;
            access_log /home/toinbis/Desktop/programming/project/
runtime/logs/project_nginx_access.log;

            location / {
                        proxy_pass  http://backend/;
                        include     /home/toinbis/Desktop/programming/
project/runtime/etc/nginx_conf/nginx_proxy_1.conf;
            }

            location  /media/ {
                        root /home/toinbis/Desktop/programming/project/
src/tsd/core/;
            }

}
}

谢谢,

3 个回答

1

谢谢你们,Euge和James,

再次非常感谢你们的帮助!

解决方案其实在这里有提到:把 proxy_set_headerHost $host; 改成 proxy_set_headerHost $host:$server_port; 就解决了问题!

1

你的设置有问题。Django认为它是在80号端口上运行。看看第一条HTTP响应中的这一行:

Location: http://127.0.0.1/admin/

很遗憾,我现在无法理解为什么会这样。在这种情况下,我更喜欢用调试工具逐步查看相关的Django代码。

1

@Eugene Morozov 指出了问题的最终结果,但我认为解决方案可能更复杂。

返回的 Location 头部信息是错误的:

Location: http://127.0.0.1/admin/

这里明显缺少了端口号。不幸的是,很难确定这个问题的来源。你可能遇到了 Nginx 或 Apache 自动修改 Location 头部的情况。我建议你可以尝试以下步骤,看看问题出在哪里:

  • 每次登录前清除你的 cookies,否则可能会得到错误的结果。
  • 直接访问你的 Apache 实例,看看问题是否依然存在。
    • http://127.0.0.1:8001/admin/
    • 如果 Location 头部没有端口号:
      • 启动 Django 开发服务器,使用一个随机的端口(比如 8005),看看问题是否依然存在:
        • 如果问题依然存在,那就是你的代码有问题。
        • 如果问题不再存在,可能是 Apache 做了一些奇怪的事情,或者 WSGI/Django 没有获取到确定端口号所需的所有信息。
          • 确保 wsgi 脚本和 django 应用都能在环境中看到端口号。
    • 如果 Location 头部有端口号:
      • 可能是 Nginx 出于某种原因把它去掉了。
      • 尝试不使用 Apache,你可能不需要它。
        • 将 Django 作为 FastCGI 服务器启动,并把 Nginx 连接到它,而不是 Apache。
          • 这样实际上可以减少服务器的一些负担(减少请求传递、额外线程、内存使用等)。
          • 这里有一个相当不错的设置指南 在这里

小补充!
不确定这是否有帮助,但似乎 Nginx 有一个选项可以在重定向时忽略端口号。这个链接已经失效,所以我从 这里 复制过来了。

http://wiki.codemongers.com/NginxHttpCoreModule#port_in_redirect

syntax: port_in_redirect [ on|off ]
default: port_in_redirect on
context: http, server, location

这个指令允许或禁止在 nginx 处理的重定向中指明端口。

撰写回答