繁体   English   中英

Python CGI 内部错误 login.html login.cgi

[英]Python CGI internal error login.html login.cgi

我目前正在尝试创建一个简单的登录页面到我在 Ubuntu 的虚拟机上运行的实际本地网页。

我在/var/www/html位置创建了LoginPage.html

HTML 文件然后调用/usr/lib/cgi-bin/login.cgi中的login.cgi文件。

我收到Internal Server Error 日志基本上只显示了这一点:

"POST /cgi-bin/login.cgi HTTP/1.1" 500 799 "http://localhost/LoginPage.html" "Mozialla/5.0 (X11; Ubtuntu; Linux x86_64; rv:84.0) Geck/201000101 Firefox/84.0

HTML 文件似乎按预期工作,但是当我按下登录并重定向到 CGI 文件时,我在 CGI 文件上收到错误消息。 我试图删除 CGI 文件中的所有内容,只留下几行但仍然出现错误。

我在cgi-bin文件夹中的其他项目文件仍然可以正常工作。

<HTML>
<HEAD><TITLE>Login Page</TITLE></HEAD>
    <BODY>
        <CENTER>
        <FORM method="POST" action="/cgi-bin/login.cgi">
            <paragraph> Enter your login name: <input type="text" name="login">
            <paragraph> Enter your password: <input type=password name="password">
            <paragraph> <input type="submit" value="Connect">
        </FORM>
        </CENTER>
        <HR>

        </form>
    </BODY>
</HTML>
#!/usr/bin/python3
import sys
import cgi
import os
import cgitb

sys.path.insert(0,'/usr/lib/project_name')
def header():
    #print "Content-type: text/html\n"
    print("<HEAD>")
    print("<TITLE> title </TITLE>")
    print("</HEAD>")

def Log():
    print("<!DOCTYPE html>")
    print("<HTML>")
    print("<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">")
    print("  <meta charset=\"utf-8\" />")
    header()
    print("BODY")
    form = cgi.FieldStorage()
    login = "login"
    password = "test123"
    if not (form):
        header("Login Response")
        print("<BODY>")
    elsif (form.has_key("login") and form["login"].value == login and form.has_key("password") and form["password"].value == password):
        header("Connected ...")
        print("<BODY>")
        print("<center><hr><H3>Welcome back,\" , form[\"login\"].value, \".</H3><hr></center>")
        print("r\"\"\"<form><input type=\"hidden\" name=\"session\" value=\"%s\"></form>\"\"\" % (form[\"login\"].value)")
        print("<H3><a href=\"/cgi-bin/projects.cgi\">Click here to start browsing</a></H3>")
    else:
        header("No success!")
        print("<BODY>")
        print("<H3>Please go back and enter a valid login.</H3>")

def footer():
    print("</BODY>")
    print("</HTML>")

print("Content-type:text/html\r\n\r\n")
cgitb.enable()
Log()
footer()

编辑:

这是解决Internal Server Errorerror.log的内容:

[2021 年 2 月 2 日星期二 08:40:41.199152] [cgi:error] [pid 10292:tid 140490049578752] [client 127.0.0.1:38888] AH01215: (2) 没有这样的文件或目录:'/usr/lib/ 的执行cgi-bin/login.cgi' 失败:/usr/lib/cgi-bin/login.cgi,referer:http://localhost/LoginPage.html [2 月 2 日星期二 08:40:41.199411]20:20 [pid 10292:tid 140490049578752] [client 127.0.0.1:38888] End of script output before headers: login.cgi, referer: http://localhost/LoginPage.html

更正设置:

没有这样的文件或目录:'/usr/lib/cgi-bin/login.cgi'的执行失败:/usr/lib/cgi-bin/login.cgi,引用者:http://localhost/LoginPage.html

确保 CGI 脚本及其父目录具有正确的权限:

chmod 755 /usr/lib/cgi-bin/ /usr/lib/cgi-bin/login.cgi

此外,CGI 脚本似乎可能有 windows 行尾,因此请确保您也删除了这些行尾,例如通过运行dos2unix login.cgi (有关详细信息,请参阅此帖子)。

解决内部服务器错误:

首先,至少进行以下更改以更正您的语法(这是导致Internal Server Error的原因):

  1. elsif应该是elif
  2. 您的header function 应该接受一个参数,即def header(title)
  3. 如果您有form.has_key ,请将其更改为使用in因为has_key现在已弃用,例如"password" in form而不是form.has_key("password")

更正后的情况如下所示:

elif "login" in form and form["login"].value == login and "password" in form and form["password"].value == password:

顺便说一句,坚持使用所有最新浏览器都支持的HTML5 ,并且现在不推荐使用center标记(它已经不再使用marquee标记)。 请改用 CSS

此外,作为一个完整的旁注,这些天来,很少看到所有大写字母用于 HTML 标签。 您在某些地方使用了该样式,但我建议放弃它以支持小写标记名称

简化 HTML 生成:

除了上述之外,我建议使用f-strings进行字符串格式化,还建议使用多行字符串来简化逻辑。

下面是一些如何增强代码的示例。

您的 header function 可能看起来像这样,按照建议使用 f 字符串和多行字符串。 title参数是可选的。

def header(title=""):
    print(f"""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="utf-8">
            <title> {title} </title>
        </head>
        <body>
    """)

您的页脚 function 可能如下所示:

def footer():
    print("""
        </body>
        </html>
    """)

最后,您的 HTML 表单可能如下所示,使用text-align: center; 对于居中:

print(f"""
    <hr>
        <h3 style="text-align: center;">Welcome back { form["login"].value }</h3>
    <hr>
    <form>
        <input type="hidden" name="session" value="{ form["login"].value }">
    </form>
    <h3>
        <a href="/cgi-bin/projects.cgi">Click here to start browsing</a>
    </h3>
""")

美化 HTML:

为了进一步美化 HTML,您可以import textwrap然后使用textwrap.dedent()从 HTML 中删除常见的前导空格(由于 Python 中的缩进),例如

print(textwrap.dedent(f"""
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title> {title} </title>
    </head>
    <body>
"""))

这有两个好处:

  1. 它在通过网络发送之前删除了不必要的前导空格 - 因此您发送的数据更少,节省带宽
  2. 当您使用客户端浏览器检查时,HTML 源代码更漂亮——对调试很有用

或者,使用 HTML 模板:

进一步的增强是利用 HTML 模板框架,例如Jinja2 这将允许您将 HTML 存储到文件中,然后通过传递变量来渲染 HTML 文件。

然后,您的 Python 代码会变得简单得多。 您只需渲染模板并传递您想要的变量。 例如,对于您 header,它可能是这样的:

template = env.get_template('header.html')
print(template.render(title='Connected ...'))

您需要先像这样设置Environment

from jinja2 import Environment

env = Environment(
    loader=PackageLoader('package', 'templates')
    autoescape=select_autoescape(['html'])
)

并将您的header.html文件放在名为templates的目录中。

您可能还想了解关注点分离原则和MVC 架构 使用这样的模板只是接近实现 MVC 的一步。

关于安全的最后一点:

看起来您正在使用 HTML hidden字段来存储用户名,并将其视为 session 令牌。 这是非常不安全的,并且不会扩展 不过,它可能足以满足您的目的。 改进它的一种简单方法是使用Set-cookie header 将其存储为 cookie,并将其设为HttpOnly ,例如

Set-cookie: session=value; HttpOnly

其中value可以是一些唯一的令牌(例如uuid )。

这比您当前的方法要好得多。

但是,更好的是,您可以PyJWT之类的库来实现安全性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM