5.6 共通功能——使用master页统一管理页面外观
在进行网页开发时,大家都会注意到,几乎所有网页的头部和尾部都是相同的外观。从统一网站的CI角度上来说,也要求所有网页的头部与尾部保持统一。除了网页的头尾具有相同的外观外,有些特定功能模块的网页还会拥有相同的网页结构,这些结构也可以共享。
在本章中,就采用了被称为master页的方式来统一管理页面的外观,将所有共同的部分放在master页中,这样既可以改善代码的品质,又可以方便网站的维护。
master页的部分:
填充部分:
要点
在MySmarty.class.php(MySmarty类)文件中定义master页的功能。本章在上一章MySmarty类的基础上,做了适当的扩展,来编写包含master页的功能。
MySmarty类中的simpleDisplay方法是在扩展display方法的基础上完成的。图5-2中显示了simpleDisplay方法的处理流程。
图5-2 master页的动作机制
如图5-2中所显示的一样,程序首先从请求URL中取得module名、controller名、action名,然后生成“APP/module名/views/smarty/templates”(常量APP为应用程序的根目录)这样的路径。最后以上述路径中的master.tpl(master页)为基础,在其中插入在“APP/module名/views/smarty/templates/controller名/action名.tpl”中定义的具体页面的内容。
这样,在view的调用方根本不用意识master页的存在。另外,对于具体的页面来讲,因为是通过module名/controller名/action名来动态地识别其对应的.tpl文件的,调用路径不用在程序中出现了。
不需要master页时,向simpleDisplay方法的第2参数传入空字符串就可以了。
目录结构
代码
将指向目录/samples/chap5/的请求都转到前台index.php。
将应用程序所在的根目录定义为常量APP。在上一章已经介绍过了,应用程序的目录应该放在Web公开目录以外,本章为了方便而将应用程序也放在公开目录之下了,实际应用时,务必将其放在Web公开目录以外。当改变公开目录路径时,请修改此处的常量定义。
此处将需要使用的外部程序包含进来。使用避免重复包含动作的require_once命令。
以下为自定义类,都是整个应用程序的共通功能,将在随后的章节中一一介绍。
生成前台控制台对象,注册各个子系统的控制类目录。本系统中以“模块(module)”的形式组织各个相对独立的子系统,必须注册了各个模块的控制(controller)类目录后,才能正确识别对应的模块。如果你想追加新的模块,必须在此注册。
这里除了注册了默认模块(default)外,还注册了bm(书签bookmark)、message(站内留言)等模块。
注册系统要使用的插件(plugin),这些插件都是系统必需的共通功能。每次都会按照注册的顺序,在正式执行页面程序前被执行。后面的章节会做详细介绍。
※请注意上述的注释,非常重要。
在要点中已经介绍过了,本系统采用Smarty来实现显示(view)功能,不再使用Zend_Controller的render模式(自动调用View脚本的功能)了,因此将'noViewRenderer'参数设置为True。
调用各个actioncontroller(或者说将控制权交给各个actioncontroller)。
通过继承Smarty来定义MySmarty类。MySmarty类的作用参照第4章。
定义默认目录。
设置默认修饰符。这里设置为'escape:"html"'后,将在显示页面前,将对模板(template)文件中的所有变量进行HTML代码变换(escape)处理。即将“<”变换为“<”等。
本节后面的补充资料中会介绍到XSS漏洞。遗漏了HTML代码变换处理将会有产生XSS漏洞的可能性。此处进行这样的设置后,不仅仅是针对模板文件中的变量,而且对所有Smarty的派生类都实行了统一的变换。
定义实际使用master页的方法simpleDisplay。simpleDisplay方法将根据请求URI,调用对应的master页/内容页(参考要点中的说明)。
参数是请求对象(request),master页的路径(可省略)。如果不想使用master页时,请向第2个参数中明确传入空值。
根据请求URI中指定的模块名(由getModuleName方法取得),设置模板文件,编译后模块文件的保存路径。
根据请求URI中指定的controller名(由getControllerName方法取得)、action名(由getActionName方法取得),以及生成内容页的相对路径(相对于template_dir的路径)。
分别在模板变量current中设置内容页的相对路径,在模板变量base中设置应用程序根URL(本系统为/samples/chap5),以及在模块变量sitemenu中设置导航路径(参见后面的5.9节)。
另外,Zend_Registry是提供操作注册表的特殊组件,同样在5.9节会有介绍。
第2参数为空或NULL时,直接调用内容页,否则调用master页用于显示。
为了调试方便追加了履历输出方法。关于履历输出的共通,参照下面章节中的介绍。
在index动作(action)中,首先生成MySmarty类的对象,只有生成MySmarty对象后才能调用simpleDisplay方法。因为simpleDisplay方法只带有一个参数,这样其master页的路径为“~/default/views/smarty/templates/master.tpl”,内容页的路径为“~/default/views/smarty/templates/index/index.tpl”。
必须要向simpleDisplay方法中传入请求(request)对象,请求对象是管理从客户端传入信息的对象,由Zend_Controller_Action::getRequest方法取得。
smarty.session是固定变量,通过其能访问session变量。这些都是在MetaPlugin类中取得的变量——标题/关键字/页面概要,分别设置在<title><meta>等tag中。
在模板变量current中设置了内容页的相对路径。这里使用{include}函数在指定的位置将其包含进master页中。
你可以自由决定基本master页的外观,但是63行的代码必须有。
由master页调用的内容页。系统的首页上将显示最新的(1月以内)最人气前10的书签(bookmark),以及最人气的用户(被大家收录为朋友最多的用户)。
补充
应用程序的组成模块
应用程序到了一定规模的情况下,进一步将其以“模块”为单位分割,管理起来将非常方便。本章的应用中,内部就由“书签系统”、“信息交换系统”等模块组成的。
在导入模块时,有几个基本的规则需要了解,归纳如下。
应用程序目录的组成
应用程序目录的组成,随着模块单位的变化而变化。本章的目录结构如下。
如上所示,应用程序目录下,以模块为单位进行目录的配置。模块下的目录组成与第4章最后介绍的应用程序的目录组成一致。总之,模块所需要的所有文件必须配置在模块目录下。
模块目录是以模块名称命名的。模块名称是可以自由命名的,默认的模块名称是“default”。
模块的注册
在应用程序中追加了新模块时,必须在控制台文件(index.php)中进行事先注册,即设置模块的controller目录。具体可以参见index.php文件的第16行到第24行。
actioncontroller的命名规则
第4章中有过关于actioncontroller命名规则的介绍,使用模块时,actioncontroller命名规则有些改变(文件名与方法名没变),如表5-6所示。
表5-6 actioncontroller命名规则
但是,默认的模块类名不用将其定义为“Default_IndexController”,定义为“IndexController”就行了。
请求URI的规则
使用模块时,请求URI变成如下形式。
但是,默认模块(default)可以省略,以下的URL是同一个意义:
XSS漏洞
XSS(cross site scripting:跨站脚本)漏洞是Web应用中可能含有的典型的安全漏洞之一。
例如有如下的脚本:
这是很简单的、入门级的代码,但是在这个代码中含有重大的漏洞。假设这是某网络论坛应用程序好了,如果哪个恶意的使用者在网络论坛上贴上了如下的链接,会出现什么情况呢?
其中http://xss.examples.com/是含有漏洞的网站,http://clacker.examples.com/是攻击者的网站。
Simple.php只是将链接中含有的Query信息输出,结果任意的JavaScript代码就这样被执行了。
如果网络论坛上含有上述的漏洞,黑客将上述链接贴在网站上后,只用单击链接,就可以盗取用户的Cookie信息。而且,如果在http://clacker.examples.com/记录下用户的Cookie后,在自动调转到原来的网页,用户连任何受攻击的迹象都感觉不到。
图5-3所示的只是一个单纯的XSS漏洞的例子。实际上,就算Cookie信息被盗取,也不至于引起很严重的问题,除非在Cookie中包含了用户的信用卡号码等重要信息。因为Cookie的特性,本来就不应该将重要的信息放在Cookie中保存。
图5-3 由恶意脚本发动的攻击实例
可以通过对输入字符串进行适当的代码转换,就可以避免上述问题。具体的就是使用escape修饰符(Smarty)或htmlspecialchars函数,将“<”、“>”、“&”等HTML的预约字符转换为“<”、“>”、“&”样的字符串。
在使用Smarty时,可以通过在default_modifiers属性中设定escape修饰符,对所有输出的变量进行强制的代码转换。
共有条评论 网友评论