perl教程018

perl教程018 - 下载...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: 下载 第18学时 基 本 窗 体 当你浏览 We b 时,肯定会填写几个 H T M L 窗体。 H T M L窗体,比如电子邮件 We b窗体、购 物窗体、宾客留言簿、在线拍卖窗体、邮件列表和订单窗体等,可以用于搜集信息,如 We b 浏览器用户的登录信息和 Web站点的首选设置等。 当用户点击这些窗体上的 S u b m i t (提交)按钮时,将会出现什么情况呢?几乎在所有情 况下,该窗体的数据都会传递给一个 CGI程序。在本学时中,我们将要介绍如何从窗体中取出 数据,如何在你的 CGI程序中对数据进行操作。 在本学时中,你将要学习: • 如何处理 Perl CGI 程序中的基本窗体。 • 如何调试 CGI窗体。 • 如何编写更加安全的 CGI程序。 18.1 窗体是如何运行的 你肯定使用过 We b 上的窗体,甚至知道窗体是如何布局的,以及它们是如何运行的。但 是,如果要确保你处理的是同一个 Web 页,那么就必须了解 HTML窗体的基本知识。 18.1.1 HTML窗体元素概述 在你开始学习窗体如何运行之前,首先应该了解 H T M L 是如何展示窗体的,以及窗体中 的所有元素起着什么样的作用。 本书中介绍的 HTML 不应该被视为最典型的 HTML。本书中讲述的 HTML 足以展示必要的 C G I 特性,但是没有涉及到太多其他的东西。在本书的代码 例子中展示的 H T M L 中没有使用 < H E A D > 或 < B O D Y > 标记,也没有使用 < D O C T Y P E >标记。此外,屏幕都非常简单朴素,你可以添加自己的 H T M L , 使屏幕更加生动和完整。 H T M L 窗体是 H T M L 文档的一个部分,用于接收用户的输入。当浏览器加载包含窗体的 HTML文档时,各个不同的 HTML标号便在 Web页上建立各个用户输入区域。用户的输入被放 入各个窗体元素中,比如复选框、单选按钮、选项菜单和文本输入项元素。当用户使用 We b 浏览器对输入元素的操作完成后,窗体通常被提交给 CGI程序,以便进行处理。 程序清单 18-1显示了一个创建的典型 HTML窗体。 程序清单 18-1 一个小型 HTML窗体 208 使用第三部分 将Perl 用于 CGI 下载 图18-1给出了: Netscape 浏览器中显示的程序清单 18-1的窗体。 图 18-1 N e t s c a p e 中显示的 程序清单 1 8 - 1 的窗 体 <FORM>标记用于设定完整的HTML文档中的窗体的开始。method属性用于设定该窗体是使用 GET还是POST方法来提交窗体。如果这个属性没有设定,浏览器将使用 ET方法将窗体提交给CGI G 程序。GET与POST方法的差异将在后面说明。 ction属性用于设定接收窗体数据的 GI程序的URL。 a C < I N P U T > 标记用于为用户提供一个输入域,在这里,它是一个空白文本框。该文本框被 赋予一个名字,它恰好是“ name” 。 <TEXTAREA>标记用于使浏览器显示一个多行文本框,以便接收输入的数据。值得注意 的重要属性是 name 属性,在这里,该域的名字是 description。HTML 窗体中的每个元素都必须 拥有不同的 name属性。当 CGI程序被赋予该窗体以便进行处理时, name属性用来区分各个域。 “每个属性都有它自己的名字”这一原则有一个例外,那就是单选按钮。单选按钮按小组 放在一起。单选按钮组中每次只能选定一个按钮。每个单选按钮组都有它自己的 name 属性。 最后显示 s u b m i t(提交)按钮。当用户单击该按钮时,窗体的值就被传递给 C G I程序,以 便进行处理,这将在下一节中介绍。 HTML 4.0 的技术规范包含了很少的不同窗体元素类型,因此,我们不想在本书中将它们 全部完整地加以介绍。例如,许多窗体元素包含了一些属性,以便安装窗体元素的某些特性, 比如前面介绍的窗体中的 T E X TA R E A 中的 r o w s 和 c o l s 。在本书的其他学时中,每当使用 HTML窗体元素时,都只使用最本的属性。 在网址 h t t p : / / w w w. w 3 c . o rg 上,你可以找到 HTML 4.0 完整的技术规范, 包括有效的窗体及其属性。 18.1.2 单击submit时出现的情况 当用户在他的 Web浏览器上填写窗体信息时,将会发生一连串的事件: • We b 浏览器接收窗体上的数据,放入名字与值对中(见图 1 8 - 2 ) 。例如,在这个示例窗 体中,名字为 b o d y 的域接收了文本输入域的值。名字为 s e x 的域将接收单选按钮的值。 209 第18学时 基 本 窗 体使用 下载 Web浏览器在发生任何情况之前执行所有这些操作。 图 18-2 浏 览器对数据与域 浏览器 的名字进行匹配 浏览器 • 对窗体域的 action部分的 URL进行访问。这是 CGI程序的 URL(见图 18-3) 。 图 18-3 Web 服务器 浏 览器与服务器进 浏览器 行联系 CGI 程序 • 使用 C G I 方法 G E T或P O S T之一,窗体上的域的名字和值被传送到 C G I 程序(见图 1 8 - 4) 。 你不必过分担心这个传输机制。 Web 服务器 图 18-4 数据被送往服务器 浏览器 CGI 程序 • CGI程序接收这些值,并生成一个应答,并将应答送回给浏览器(见图 18-5) 。该应答可 以是个 H T M L页,或者包含另一个窗体的 H T M L页,也可以是转到另一个 U R L 的H T M L 或者是 CGI程序能够生成的任何其他东西。 Web 服务器 图 18-5 W e b 服务器的 C G I 浏览器 程序作出的应答 CGI 程序 18.2 将信息传递给你的CGI程序 当由于窗体的提交而使 CGI程序运行时,从窗体传递过来的域的名字和值(称为参数)必 须由 CGI程序来处理。这是使用 param函数来处理的。 如果没有任何参数,那么 p a r a m函数返回传递到 C G I 程序中的域的名字。如果 C G I程序接 收到程序清单 18-1 中的窗体, param函数将返回 body、sex 、name和submit。 如果带有参数, p a r a m函数返回该参数的值。例如, p a r a m ( ‘s e x’ ) 将根据你的选择,返 回单选按钮的值 male或female。 程序清单 18-2包含了用于输出这些参数的简短的 CGI程序。 程序清单 18-2 用于输出参数的 CGI程序 210 使用第三部分 将Perl 用于 CGI 下载 如果 param函数指定的参数没有用于该窗体,则 param返回 undef。 GET与POST方法 在程序清单 1 8 - 1中的窗体内, < F O R M > 标号拥有一个属性,称为 m e t h o d 。M e t h o d属性用 于设定 Web浏览器应该如何将数据传送到 Web服务器。目前可以使用的方法有两个。 第一个方法称为 G E T ,如果你在 < F O R M > 标号中没有设定方法,那么这就是默认的方法。 使用 G E T 方法,通过在 U R L 中对窗体值进行编码,就可以将这些值传递给 C G I 程序。当你在 Web 上冲浪时,可能看到下面这样的 URL: C G I程序运行时,能够将 U R L 的剩余部分解码,使之分解成域和值。当你调用 p a r a m函数 时,它实际上也是进行这样的操作。你不应该试图自己对这些值进行解码。 p a r a m函数能够全 面地进行这项操作,你没有理由使用别的方法来提取这些值。 另一个方法是 P O S T,它产生的结果完全相同,但使用的手段不同。不是将所有的窗体值 编码后放入 U R L,而是通过访问 We b服务器,然后将 H T M L 窗体值传送给 C G I程序,作为其输 入数据。另外,现在你不必清楚地了解这个过程究竟是如何运行的, CGI模块会为你处理好这 个问题。只要调用 param函数,就可以读取这些值,对它们解码,然后将它们传递给你的程序。 你可能已经从 I n t e r n e t 下载了一些 C G I程序,或者在别的书中见过一些例 子,通过对环境变量 Q U E RY _ S T R I N G 进行解码,或者使用变量 R E Q U E S T_ M E T H O D 来确定窗体是使用 G E T还是 P O S T方法。这些程序试图重复进行在 标准 C G I 模块中已经做的工作但是也可能没有这样做。你应该避免自己执 行这项操作。 那么究竟你应该选择哪一种方法呢?每种方法都有它的优点和缺点。 GET方法使得 Web浏 览器能给生成 Web 页的特定 URL做上书签。例如下面的 URL 可以做上书签,并且总是由浏览器返回。从 CGI程序 sample.pl 的角度来看,它不知道你刚 刚是否查看了该窗体。它像往常一样接收通常的 CGI参数。如果能够使用 GET方法的 URL编码 值来反复调用一个 CGI程序,这称为幂等性。 但是你可能不是特别想使浏览器能在你的站点中做上书签,以便直接运行你的 C G I程序, 坦率地说,用于以 GET方法启动 CGI程序的 URL是很讨厌的。 P O S T方法根本不对 U R L 中的窗体数据进行编码,当它为 We b页进行处理时,它依靠浏览 器发送数据。但是,由于数据并没有被编码后放入 U R L,因此你无法使用 P O S T 方法给 C G I程 序生成的 Web页做上书签。 211 第18学时 基 本 窗 体使用 下载 18.3 Web安全性 在你将 CGI程序放到 World Wide Web 上去之前,必须了解下面几个问题。通过将 CGI程序 放在 Web页上,你就为远程用户(使用 Web浏览器)赋予对你的系统的有限访问权。使用普通 H T M L 文档,他们只能从你的 We b站点检索静态文档。但是,使用 C G I 程序,他们就能在你的 Web服务器上运行程序。 懂得如何编写安全而保密的 CGI程序后,你与你的 Web服务器管理员一定会感到更加高兴。 编写这样的程序并不难,只需要掌握几条简单的注意事项。 18.3.1 建立传输明码文本的连接 当 We b 浏览器从 We b 服务器中检索 We b 页时, H T M L 是通过一个明码文本信道来发送的 (见图 1 8 - 6) 。这意味着当数据一路通过 I n t e r n e t 时,它并不进行加密、编码,否则就无法被对 方理解。 图 18-6 明 码文本被传送到 服务器 Internet Web 服务器 浏览器 “将药品运往我在…的家” 用户填入窗体然后提交给你的 C G I程序的数据,传输时所用的协议与初始 We b页使用的协 议相同。任何人只要访问窗体,就可以查看它的所有域(见图 18-7) 。 Internet 图 18-7 服 务器用明码文本 作出应答 Web 服务器 浏览器 “很抱歉,比尔,你的信用卡无效” 用明码传送数据时存在的问题确实是你应该担心的问题。 I n t e r n e t 不是一个安全的地方, 在Web浏览器与 Web服务器之间的线路上的任何人都能够窃听线路上来回传送的信息。 应该记住,决不应该以普通 CGI窗体来发送下列几种类型的数据: • 任何形式的口令。 • 个人信息(社会保险号,电话号码) 。 • 财务信息(帐号,个人身份识别号,信用卡号码) 。 请记住这些基本原则。决不要在 Internet上发送你不会写在明信片上任何信息。 你会说: “等一等,我曾经在 I n t e r n e t上看到一些窗体,要求查询所有上 述信息,并且说这是安全的。 ”使用某些辅助工具,可以在 We b 上执行相当 安全的事务处理。若要执行安全的 We b事务处理,实际上必须对浏览器/服 务器之间的全部会话进行加密。这是通过运用 h t t p 协议的安全版本 h t t p s 来实 现的。 212 使用第三部分 将Perl 用于 CGI 下载 18.3.2 注意不安全数据 在编写安全的 C G I 程序时需要考虑的另一个问题是:你编写的程序将根据 We b 页提供给你 的输入来执行 P e r l 命令。 I n t e r n e t 或者你的 I n t r a n e t(专用网)上有许多人属于不良之徒,他们 以损害你的 We b 服务器为乐,并因此而感到自己了不起。还有一些并无恶意的用户可能不小 心将无效数据发送给你的 CGI程序。 请看程序清单 18-3中的 HTML窗体和程序清单 18-4 中的 CGI程序。 程序清单 18-3 程序清单 18-4 目录清单 Web窗体 名字为 directory.cgi的不安全 CGI程序 程序清单 1 8 - 3为用户提供了一个简短的窗体,用于接收一个目录名,再将它传送给称为 d i r e c t o r y. c g i 的 C G I 程序。在程序清单 1 8 - 3 中, d i r e c t o r y. c g i 程序接收该目录,并为 D O S / windows 用户对它执行 ls -1 命令,它与 dir等价,为用户提供一个目录列表。 这种类型的程序使得远程 We b冲浪者能查看你的整个目录结构。 C G I程序并不检查该目录 名是什么,如果浏览器想要查看你的敏感数据,它就可以查看。 更重要的一个问题是: $ d i r e c t o r y可能根本不包含任何目录。如果 We b浏览器为 d i r n a m e发 回了值 /home;cat /etc/passwd,这时, CGI程序运行的命令将类似下面的形式: 这个命令将能有效地将系统的口令文件拷贝发回给 Web浏览器。实际上,所有 UNIX shell 命令或 MS-DOS命令都可以这样运行。如果你的 Web服务器尚未正确地安装,那么任何用户都 可以上 Internet 。 Perl拥有一个机制,可以帮助你避免做这样的傻事。#!行上的 -T开关可以激活数据受感 染特性。当数据从外部信息源(如文件句柄、网络套接字、命令行等)接收过来时,它就被 做上“ tainted(受感染 ) ”标记。受感染的数据不能用在反引号、系统函数调用(如 open 函数) 、 系统命令或可能破坏安全性的其他地方。 当受感染检查正在进行时,不能将 o p e n函数、 s y s t e m函或反引号用于你的 P e r l程序,除非 首先明确设置 PATH 环境变量。 程序清单 18-5显示了这个程序的更加安全的版本。 程序清单 18-5 directory.cgi程序的更安全版本 213 第18学时 基 本 窗 体使用 下载 若要了解关于受感染的数据、如何消除数据的感染以及如何编写安全的 Perl程序的详细信息,请参见 Perl 产品包含的 Perlsec手册页。 18.3.3 从事无法执行的操作 HTML/CGI 窗体也可能遭到另一种情况的损害。请看程序清单 18-6中的 HTML窗体。 程序清单 18-6 一个简单的窗体 在这个窗体中, c o l o r域允许的最大宽度是 1 5 。这对吗?大概差不多。 H T M L技术规范规 定,文本域的 length最多允许这么多的字符。但是,浏览器可能发生故障,有人可能故意在这 个域中放入 15个以上的字符,方法是不使用你的窗体,或者创建一个新窗体。 如果你希望某个域拥有一个特定值,请不要依赖 H T M L 、 J a v a或 J a v a S c r i p t 来保证这个值 的正确性。例如,如果 c o l o r域的绝对限值应该是 1 5 ,那么 P e r l 程序可以像下面这样对它进行 处理: 18.3.4 拒绝服务 通过拒绝服务,任何 Web服务器的性能都会受到削弱。由于 Web服务器是代表远程用户处 理访问请求的,因此,如果远程用户发出的访问请求太多, We b 服务器就会不堪重负。这种 做法有时是恶意的,而且常常是恶意的。许多时候,一些公司为 We b 提供了许多服务,结果 为了响应用户的访问请求,负担太重,因此不得不关闭这些服务,重新考虑自己的做法。 静态 HTML页或 CGI 程序也会出现拒绝服务的情况。 为了防止拒绝服务的问题,你有时会感到无能为力,除非手头拥有足够的服务系统,能 够处理浏览器的负荷。如果你的 CGI程序花费很长时间来执行或使用相当一部分系统资源(如 文件访问的频率, C P U使用的密度) ,以便使程序能够运行,服务器将很容易受到拒绝服务的 攻击。你应该设法尽量缩小你运行的 CGI程序的规模,并使之更快地运行。 214 使用第三部分 将Perl 用于 CGI 下载 18.4 宾客留言簿 这个例子使你能够为 Web站点编写定制的宾客留言簿。宾客留言簿是个 HTML 窗体,在这 个窗体中,用户可以指明来宾的名字并配有一些说明。宾客留言簿可以用来收集关于某个问 题的反馈信息,作为一个简单的消息板,或者将问题提交给帮助桌。数据保存在一个文件中, 并且可以在窗体信息填满后显示出来。它也可以在它自己的 Web页上显示。 程序清单 18-7 提供了一个简短的 HTML代码段,它展示了一个用于虚构帮助桌的宾客留言 簿窗体。你当然可以修改这个窗体,使之适合你自己的需要。 程序清单 18-7 帮助桌窗体 这个帮助桌窗体需要运行一个名叫 / c g i - b i n / h e l p d e s k . c g i的 C G I 程序。程序清单 1 8 - 8显示了 这个 C G I 程序。如果你想要将该 C G I程序放在另外某个位置,或者将它称为另一个名字,请务 必将正确的 URL输入程序清单 18-7 的帮助桌窗体中。 程序清单 18-8 帮助桌 CGI程序 下载 215 第18学时 基 本 窗 体使用 程序清单 18-8中的大部分代码是你已经熟悉的 Perl程序,不过请特别注意下列几个问题: • get_lock()和release_lock()这两个函数对于这个窗体是绝对必要的。对于任何一个CGI程序来 说,你始终必须假设任何时候都可能有 CGI程序的多个实例正在运行。写入帮助桌日志文 件的helpdesk.cgi的多个实例将会出错,因此在将信息写入文件之前,该文件应被锁定。在 读取文件之前,它不锁定,因为一边读取日志文件,又一边写入文件,那将是很糟糕的。 • 这个 C G I 程序有两个目的。当作为程序清单 1 8 - 7中的窗体的目标操作来调用时,它将新 项目写入日志文件。当不使用该窗体来调用该程序时,它只显示日志文件的内容。 18.5 课时小结 在本学时中,我们介绍了 H T M L窗体与 C G I程序如何进行交互操作,如何使用 C G I模块的 p a r a m 函数使你的 C G I 程序能够转换窗体的内容。另外,还介绍了怎样才能使你的 C G I 程序更 加安全,如何处理受感染的数据。我们还介绍了一个简单的 CGI宾客留言簿应用程序,你可以 对它定制和修改,以便适应你自己的需要。 18.6 课外作业 18.6.1 专家答疑 问题: 我无法使用窗体的提交功能,老是出错,怎么办? 解答: 请使用第 1 7 学时中介绍的 C G I调试指南,找出存在的问题。仅仅因为它是个窗体, 216 使用第三部分 将Perl 用于 CGI 下载 并不意味着调试该窗体与调试普通 CGI程序有什么不同。 问题: 我在 I n t e r n e t 上看到了这个出色的程序,但是我不懂得为什么它试图使用 $ENV{QUERY_STRING}来获得窗体参数。为什么? 解答: 因为该程序的开发人员决定放弃该 CGI模块的窗体处理功能。这个情况说明它可能 是该 C G I 模块以前的一个非常老的 P e r l程序,也可能程序开发人员决定使用他自己的窗体处理 代码。不管属于哪种情况,这表明你应该用警惕的目光观察这个程序,并且小心地使用它。 问题: 我通过命令行提示符运行程序,其#!行上有一个选项 - T ,我得到一条出错消息 Too late for -T option (运行 -T选项太晚了) ,然后程序停止运行了。为什么? 解答: 你应该尽快将 -T 选项赋予 Perl程序,这样它就知道要去寻找受感染的数据。当你的 程序中的#!行被处理时,这就太晚了, Perl已经处理了你的没有感染的命令行选项。若要从 命令行提示符来运行 Perl 程序,例如在调试程序中运行,你也必须在命令行提示符上设定 -T: Perl -T -d foo.cgi 问题: P e r l的数据受感染功能是否能使我避免在 C G I程序中犯一些愚蠢的错误?它们现在 是否能够确保安全? 解答: 没有一个 C G I 程序是绝对安全的。 P e r l的数据受感染功能在很大程度上可使你不犯 愚蠢的错误,不过它们无法保证你编写出安全的程序。 18.6.2 思考题 1) 在数组上下文中,不带参数的 param函数将返回 a. undef b. 窗体元素的数目 。 c. 窗体元素名的列表 。 2) 如果你使用 CGI 模块, POST与GET方法之间的差别是清楚的。 a. 是。 b. 否。 3) HTML 窗体上的 password域的输入类型是安全的,因为它在发送前会对口令进行加密。 a. 是。 b. 否。 18.6.3 解答 1) 答案是 c。如果不带参数, param将返回来自提交的窗体的元素名列表。 2) 答案是 a。 3) 答案是 a 。在普通 H T T P和 C G I 程序中,所有窗体域都是以明码文本传送的,因此是不 保密的。口令域输入类型只在你键入口令时将该域隐藏起来而已。 18.6.4 实习 • 对帮助桌窗体稍作修改。将时间戳添加给每个项目,并且给输出添加某些颜色。 • 问题: d i s p l a y ( )函数从最老的项目开始输出帮助桌窗体中的各个项目。请修改 d i s p l a y ( ) 函数,使之首先输出最新的项目。 ...
View Full Document

Ask a homework question - tutors are online