Python重定向无效

1 投票
2 回答
3437 浏览
提问于 2025-04-18 15:53

我想把用户重定向到我的主页。这个操作应该很简单,像这样:

print "Location:http://localhost:8000/index.html"
print ""

但是出了一些问题,这个方法没有奏效。我在Kali Linux上运行CGIHTTPServer,使用的是Python 2.7.3。当我尝试运行这个脚本时,它只是打印出:

Location:http://localhost:8000/index.html

我还试过用127.0.0.1代替localhost,但也不行。下面是我尝试运行的CGI脚本:

#!/usr/bin/python
import MySQLdb,cgi, os, sys
db=MySQLdb.connect(host="localhost", user="root", passwd="", db="test")
flag=False
query = db.cursor()
sys.stdout.write("Content-type: text/html\r\n\r\n")
sys.stdout.write("")
sys.stdout.write("<html><body>")
form = cgi.FieldStorage()
name = form.getvalue('temp')
passwd = form.getvalue('temp2')

if(query.execute("select * from cred where uname='"+name+"' and pass='"+passwd+"'")):
    db.commit()
    sys.stdout.write("Hello "+name)

else:
    db.commit()
    flag=True
sys.stdout.write("</body></html>")

if(flag == True):
    print "Location:http://localhost:8000/"
    print ""

2 个回答

4

根据被接受的答案,你需要使用 Status: 302 FoundStatus: 301 Moved Permanently 这样的状态头,并且还要加上 Location 头,才能正确地进行重定向。

另外,Python 内置的 CGIHTTPServer 无法执行重定向(HTTP 代码 302),因为在执行 CGI 脚本之前,它会先发送代码 200(表示脚本输出开始)。这就导致状态码被提前发送了。 (https://docs.python.org/2/library/cgihttpserver.html)

不幸的是,在 Python 3 中也是这样。 (https://docs.python.org/3/library/http.server.html#http.server.CGIHTTPRequestHandler)

关于这个问题有一个讨论贴 (http://bugs.python.org/issue10487),但目前为止,还是没有办法使用状态头。其他的 CGI 服务器应该不会有这个问题。

3

你这里有两个问题:

  1. 总是在开始时写Content-Type头部加上额外的换行。这样一来,你就完成了所有的头部,之后就不能再添加更多了。

    只有在进行重定向的时候,才写这些头部

  2. Location头部只用于重定向,也就是状态为30x的HTTP响应。你需要添加一个Status:头部,告诉网络服务器返回一个不是200的状态。

调整你的代码来解决这些问题:

#!/usr/bin/python
import cgitb
cgitb.enable()

import MySQLdb, cgi, os, sys

db = MySQLdb.connect(host="localhost", user="root", passwd="", db="test")

form = cgi.FieldStorage()
name = form.getvalue('temp')
passwd = form.getvalue('temp2')

with db as query:
    query.execute("select * from cred where uname=%s and %s", (name, passwd))
    result = query.fetchone()
    
if result is None:
    # no such user, redirect
    print 'Status: 302 Found'
    print 'Location: http://localhost:8000/'
    print

else:
    print 'Content-type: text/html'
    print
    print '<html><body>Hello {}</body></html>'.format(name)

注意,我对代码做了一些修改,采用了一些最佳实践:

  1. 绝对不要使用字符串插值把用户信息放进SQL查询里。这样会遭到SQL注入攻击。应该使用SQL参数,让数据库驱动程序帮你处理这些值。

  2. 你可以把连接当作上下文管理器来自动提交。

  3. 我使用字符串格式化来生成HTML输出。

撰写回答