利用session,cookie进行安全性控制

来源:互联网 发布:开通淘宝需要什么条件 编辑:程序博客网 时间:2024/05/02 21:17
 利用session,cookie进行安全性控制
             
            Sessions的介绍
            什么是Sessions?session其实指的就是访问者从到达某个特定主页到离开为止的那段时间,每个访问者都会单独获得一个session。
            Sessions可以用来储存访问者的一些喜好,例如:访问者是喜好绿色背景还是兰色?访问者是否对分屏方式怀有敌意。以及访问者是否宁可浏览纯文本的站点,这些信息可以依据sessions来跟踪。
            Sessions还可以创建虚拟购物篮。无论什么时候用户在你的网站中选择了一种产品,那么这种产品就会进入购物篮,当他或她准备离开时,就可以立即进行以上所有选择的产品的订购。这些购物信息可以被保存在Session中。
            最后,Sessions还可以用来跟踪访问者的习惯,就象现在环境学者跟踪大白鲨生活习性一样。你可以跟踪你的访问者从一个主页到另一个主页,这样对于你对站点的更新和定位是非常有好处的。
            
            Sessions的使用和处理
            Session的发明是填补HTTP协议的局限,请注意HTTP协议是怎样工作的-用户发出请求,服务端作出响应,这种用户端和服务端之间的联系就是离散的,非连续的。
            在HTTP协议中没有什么能够允许服务端来跟踪用户请求。在服务端完成响应用户请求后,服务端不能持续与该浏览器保持连接。从网站的观点上看,每一个新的请求都是单独存在的,因此,HTTP协议被认为是stateless协议,在用户在多个主页间转换时,你就根本无法知道他的身份。
            Sessions的引用就是弥补了这个缺陷。利用Sessions,你就可以在一个用户在多个主页间切换的时候也能保存他的信息。这样很多以前根本无法去做的事情变得简单多了。
            注意
            现在还有很多浏览器不能支持Cookies,如果想要具体了解这些,看后面的相关部分。
            开始Session信息
            Active Server
            Pages的Sessions非常好用,你能够利用Session对象来对session全面控制,如果你需要在一个用户session中存储信息,你只需要简单的直接调用Session对象就可以了,下面是个例子:
            <HTML>
            <HEAD><TITLE>Session示例</TITLE></HEAD>
            <BODY>
            <%
            Session(“Greeting”)=“欢迎!”
            Response.Write(Session(“Greeting”))
            %>
            </BODY>
            </HTML>
            当Active Server
            Page执行时,浏览器上显示出”欢迎!”的字段,脚本第一行是给Greeting赋值为”欢迎!”,第二行将这个字段显示出来。
            不过,这种操作没什么大不了的,但是,可以假象一个同样的用户进入另一个主页,例如,下面这个Active Server Pages:
            <HTML>
            <HEAD><TITLE>另一页</TITLE></HEAD>
            <%=Session(“Greeting”)%>
            </Body>
            </html>
            当他进入这页,同样的”欢迎!”又显示出来了,注意这一页没有赋值操作,这个Greeting变量的值是前面那页赋值的。
            你无法用普通的脚本变量来进行这种处理,因为一般的变量只在一个单独主页内有效,而Session变量在用户离开网站前一直存在生效。
            要理解的很重要的一点是Session变量是针对特定用户相联系的。针对某一个用户赋值的Session变量是和其他用户的Session变量完全独立的,不会存在相互影响。换句话说,这里面针对每一个用户保存的信息是每一个用户自己独享的,不会产生公享情况。例如下面这个例子(针对于注册表的例子):
            <%
            Session(“Myname”)=Response.form(“Username”)
            Session(“Mycompany”)=Response.form(“Usercompany”)
            %>
            很明显,对于不同的用户,Session的Myname变量和Mycompany变量各自是不同的,在每个人在网站的不同主页间浏览时,这种针对这个个人的变量会一直保留,这样作为身份认证是十分有效的。
            
            Session的内容
            几乎所有的Session存储的内容存在Content集合中。例如,下面两个语句是等效的:
            <% Session(“MyVar”)=“Some data” %>
            <% Session.Contents(“MyVar”)=“Some data” %>
            正如前面对集合的讨论中说道的,你仍然可以利用Count属性来检查集合的数量。同样你也可以利用FOR EACH,FOR
            ...NEXT循环来显示Content所有内容。下面的例子使用了这些方法:
            <%
            Session(“Username”)=“谢建云”
            Session(“Usercompany”)=“迈至科网络”
            %>
            这里面Session对象的Content集合一共有<%=Session.Content.Count%>项。
            <hr>
            <%
            FOR EACH thing IN Contents
            Response.Write(“<br>“&thing&Session.Contents(thing))
            NEXT
            %>
            <hr>
            <%
            FOR I=1 to Session.Contents.Count
            Response.Write(“<br>“&Session.Contents(i))
            NEXT
            %>
            在这个脚本中,创建了两个Session变量,Username和Usercompany,然后,依次通过FOR
            EACH和FOR...NEXT循环的方法将这两个字段内容显示出来,和前面的章节中十分类似

            Session结束的控制
            服务器怎么知道一个Session结束了呢?换句话说,怎样知道是否已经离开了这个站点而去了另一个站点或者已经关掉电脑看电影去了呢。如果一个人一直没有提出请求或者刷新主页长达20分钟,那么服务器就默认为用户已经离开了。这种策略就使得服务端可以释放对用户进程进行跟踪时使用的资源。
            对于有些网络站点,20分钟显然有些短,例如,对于高水平选手进行的网络围棋,很多步子是要长考的。那么这时候20分钟如果释放了资源,这个棋手就可能被服务端轰出局,这就不爽了。
            有些网络站点则相反,资源有限而访问量又很大,没有什么需要耗费时间的信息传递,那么白白浪费资源是很可惜的,也会使其他访问者的访问速度受到影响。
            不过,对于Active Server
            Pages来说,对这些进行控制都没什么难度,Session对象有这种Timeout属性,你完全可以限定一个Session存在的限定时间。例如:下面这个脚本将限制时间设为60分钟:
            <% Session.Timeout=60 %>
            注意
            你也可以利用Internet Service Manager来进行这种控制。从Application设置对话框中,点击Active
            Server Pages表并且限定Session的限制时间。
            当用户的Session时间过期后,如果用户刷新了主页,那么将被认为是新的访问者,所有以前的Session信息会全部失去。你也可以利用Abandon方法来消除一个Session。这里再引入一个SessionID属性,这将自动分别为每一个Sessioin分配不同的编号。
            <HTML>
            <HEAD><TITLE>Abandon Session</TITLE></HEAD>
            <BODY>
            <BR>这个用户自动编号为<%=SessionID %>
            <% Session.Abandon %>
            <BR>这个用户自动编号为<%=SessionID %>
            </BODY>
            </HTML>

            Sessions事件
            和其他对象不同的是,Session对象中有事件(Event)。一共两种:Session_OnStart事件,当一个Session开始时被触发。还有Session_OnEnd事件,当一个Session结束时被触发。在一个脚本中你可以和其中一个并且只能和其中一个事件关联。
            在事件触发时下面这些脚本的语句被执行。这两个脚本位于特定的文件Global.asa。这个文件位于你的网站应用的根目录。它包括了一些通用程序段和你的网站应用。Global.asa文件有如下结构:
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Application_OnStart
            END SUB
            </SCRIPT>
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Application_OnEnd
            END SUB
            </SCRIPT>
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Session_OnStart
            END SUB
            </SCRIPT>
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Session_OnEnd
            END SUB
            </SCRIPT>
            注意
            下一章提供更加详细的关于Global.asa文件的内容
            Global.asa包括四个脚本。这里面有一个是根据Session_OnStart触发,另一个是根据Session_OnEnd触发(下一章介绍剩下的另外两个脚本)
            请注意Global.asa使用了微软的HTML拓展<SCRIPT>标记语法来限制脚本,这也就是说,你必须用<SCRIPT>标记来引用这两个事件而不能用<%和%>符号引用。例子中Global.asa使用的是VBScript,但是你也可以使用其他脚本语言。
            在Global.asa中不能有任何输出语句,无论是HTML的语法还是Response.Write()方法都是不行的,Global.asa是任何情况下也不能进行显示的。
            你只需要在Global.asa中添加一些你希望执行的脚本,那么只要Session一创建,这些脚本就会自动执行,例如下例:
            <SCRIPT LANGUAGE=VBScipt RUNAT=Server>
            SUB Session_OnStart
            Session(“Username”)=“Unknow”
            Session(“Userpassword”)=“Unknow”
            END SUB
            </SCRIPT>
            这个脚本将”Unkonw”值赋给了Username和UserPassword变量。这个例子将在任何一个Session 创建的时候就执行。
            Session_Onstart脚本可以用于很多种目的。例如,你希望访问者必须浏览某一个主页,下面的例子就在用户进程开始时进行了这种引导,那么这里面使用Response.redirect方法。下面是这个例子:
            <Script Language=VBScript RUNAT=Server>
            SUB Session_OnStart
            MyHomepage=“/homepage.asp”
            RequestPage=Request.ServerVariables(“SCRIPT_NAME”)
            IF NOT (STRCOMP(MyHomePage,RequestPage,vbTextCompare)=0) THEN
            Response.Redirect MyHomePage
            END IF
            END SUB
            </SCRIPT>
            在这个脚本中,用户请求和主页路径进行比较,如果不是一样的,用户就被自动引导到该主页。
            下面的例子将Session_OnStart和Session_OnEnd都进行了使用:
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Session_OnStart
            Response.AppendToLog Session.SessionID&” Starting”
            END SUB
            </SCRIPT>
            <SCRIPT LANGUAGE=VBScript RUNAT=Server>
            SUB Session_Onend
            Response.AppendToLog Session.SessionID&” Ending”
            END SUB
            </SCRIPT>
            这个例子中,当用户的Session开始时,日志文件中记录了该用户的Session和Starting信息;当用户的Session结束时,日志文件就记录了该用户的Session结束的信息。这样,你就可以作很多种判断统计,例如说每个人的停留时间、站上现在有多少人等等。这样对于站点设计和定位就很有助益。
            
            Session是怎样工作的?
            Session其实是利用Cookie进行信息处理的,(参见后面有关Cookies的介绍),当用户首先进行了请求后,服务端就在用户浏览器上创建了一个Cookie,当这个Session结束时,其实就是意味着这个Cookie就过期了。
            为这个用户创建的Cookie的名称是ASPSESSIONID。这个Cookie的唯一目的就是为每一个用户提供不同的身份认证。
            注意
            如果你对名字是ASPSESSIONID的COOKIE感到好奇,你可以利用ServerVariables集合的COOKIE
            Header来接受这个信息,参看下面这个脚本:
            <%=Request.ServerVariables(“HTTP COOKIE”) %>

            Session变量自己不会存在用户浏览器上。不过,ASPSESSIONID这个cookie需要使用session变量。server使用ASPSESSIONID
            cookie来将特定的用户和特定的session信息联系起来。没有cookie的话,Server就不会了解到每一个特定用户在网站中移动的信息。
            利用SessionID变量存储ASPSESSIONID
            cookie和直接对名为ASPSESSIONID的cookie赋值有很大不同。微软利用了一个复杂的数学算法对SessionID进行了加密措施,以防止黑客猜测出SessionID的值并且依据这个获得不该获得的身份或权限。
            注意
            你可以用两种方法屏蔽掉SessionID,一种是将全站进行屏蔽,另外一种是将一个单独Active Server Page进行相应屏蔽。
            如果想要将整个站点的Session操作进行屏蔽,你可以使用Internet Service
            Manager。从Application设置对话框,点击Active Server Pages表并且取消对Enable Session
            State选项的选择。
            你还可以在特定的Active Server Page的首行加入使之屏蔽的语句来进行这种操作。
            <% EnableSessionState=False %>
            由于Session对象使用了Cookies,那么它的兼容性就受到了限制,一些老的浏览器显然是不行的,新的浏览器象是NetScape4.0也提供了屏蔽Cookie的选项。
            这样就出了问题、由于Cookie不能适用于所有浏览器,那么在建站时你就必须注意了,如果你的网站定位于大众通用,就必须考虑各种不同的用户情况。不过现在确实有可以替代的方法,有些取代Cookies来进行身份认证的方法将在后面的章节中进行讨论。
            注意
            当前浏览器,是否发送一个Cookie在URL是区分大小写的,因此,微软提醒你最好使用同样的大小写方式,例如一起使用/WWW/mypage.asp和/www/mypage.asp肯定会使浏览器出错。
            
            Cookies
            很少有网络技术能够象cookies来在网络用户间制造这样大的争论。Cookies只是一个无辜的名字,但是许多用户将这与邪恶的目的连在一起。
            Netscape首先在它的浏览器中引入了cookies,从那时起,World Wide
            Web协会就支持cookie标准。大部分浏览器现在都兼容cookie的使用。
            Cookies是什么?浏览器用一个或多个限定的文件支持Cookie。这些文件在Windows机器上叫做Cookie文件或者在Macintosh中叫做magic
            cookie文件,被网站用来在上面存储Cookie数据。网站可以在这些Cookie文件中插入信息。这样对有些网络用户就有些副作用。有些用户认为这造成了对隐私的侵犯。更糟的是:有些人认为Cookie是对个人空间的侵占。
            目前有些Cookie是临时的,还有一些则是持续的。例如,cookies被Active Sever
            Pages用来跟踪用户进程直到用户离开网站。另外有些Cookie则保持在Cookie文件中直到用户返回时又进行调用。
            在cookie文件中保存cookies会产生很大的问题。主要是有些用户担心会跟踪用户网上冲浪的习惯。害怕这种信息如果落入一些‘黑手’,那么个人也就可能成为一大堆广告垃圾信笺的对象,不过,这种担心根本不会发生,因为无法跨过网站来获得cookie信息,以这种目的来应用Cookie是不可能的。不过,由于一些用户错误的理解以及‘以讹传讹’,一些浏览器开发商别无选择只能作出响应(例如Netscape4.0提供了屏蔽Cookie的选项)。
             
            注意
            目前一些有关Cookie侵犯隐私权的讨论已经到了歇斯底里的地步,甚至包括网站站长、专家级的一些人物也在这种认识上犯过错误。
            目前的主流浏览器是这样的,IE和NETSCAPE都提供了附加的控制Cookie的手段,其中NETSCAPE4.0不但可以对接受Cookie进行警告,而且还可以屏蔽掉Cookie,
            IE3.0也可以屏蔽Cookie,但是由于微软开发出了Active Server
            Pages,因此在IE4.0中就只能进行接受警告而没有提供屏蔽选项。
            更过分的是,很多技巧的技术甚至已经可以在不能屏蔽cookie的浏览器上进行Cookie的屏蔽。例如,将你的cookie文件作成只读(参见http://www.cookiecentral.com)
            很不幸,由于上述原因,你的网站利用Cookie就会有各种麻烦,甚至造成Session的调用失败。
            Cookie是怎样工作的
            Cookies将通过HTTP Headers来从服务端返回到浏览器上。服务端首先在响应中利用Set-Cookie
            header来创建一个Cookie,浏览器后面的请求的cookie header中就会返回这个Cookie来完成浏览器的认证。
            假设你创建了一个名字为UserName的Cookie来包含访问者的信息,创建Cookie时,Server的Header就象下面(假设访问者为Bill
            Gates):
            Set-Cookie: UserName=BILL+Gates;path=/;domain=aspsite.com;
            expires=Tuesday,01-Jan-99 00:00:01 GMT
            这个Header就在浏览器的电脑上的Cookie文件中添加了一条记录。浏览器将名字为UserName的Cookie赋值为Bill
            Gates。请注意这个cookie的值是进行了URL-encoded操作的。
            后来,header通知浏览器将cookie通过请求以忽略路径的方式返回服务端,因此,一个Cookie设定后,其应用的所有文件就必须在同一个目录下,例如如果开始指定的路径是/private目录,那么cookie
            Header对文件:/private/mypage.asp的请求就可以,而/mypage.asp由于路径变动就无法利用这个Cookie了。
            domain属性能够在浏览器端更加对cookie发送进行限定。在这个例子中,cookie只能传到指定的服务器上,而决不会跑到什么www.yahoo.com或者什么其他网站。
            注意
            现在的浏览器在判断Cookie的路径时是区分大小写的,这就意味着如果路径是/private,那么以/PRIVATE路径方式就无法进行这个Cookie的调用和认证。
            最后,Expires标记限定了Cookies的过期时间,在例子中的Header中,限定浏览器将该Cookie保存到1999年1月1日第一秒,实际上,浏览器在接受的Cookie很多时,还会自动进行删除。
            浏览器创建了一个Cookie后,在每一个针对该网站的请求时就都会在Header中带着这个Cookie,也就是每一次满足该路径的情况下这个Cookie都会有效。不过,对于其他网站的请求Cookie是绝对不会跟着发送的。浏览器会这样一直发送到Cookies过期为止。Cookie
            Header如下:
            cookie: username: Bill+Gates
            在Active Server Pages中创建和读取Cookies
            当利用Active Server
            Pages创建了一个cookie之后,你就可以使用Response对象的Cookie集合了。你可以创建两种cookie;一种是单值的,另一种可以认为是cookie字典类型,即允许多个键值对的存在。
            创建单值的相对简单,如下脚本:
            <% Response.Cookies(“Username”)=”Bill Gates”
            Response.Cookies(“Username”).Expires=”Jan 1,1999”
            %>
            这个脚本的工作一目了然,将名字为Username的Cookie赋值为Bill Gates,
            同时将过期时间限定为1999年1月1日,这里面需要说明的是,Expires属性如果不进行赋值,那么默认的就是用户一离开网站就过期。
            由于这个例子脚本创建的是Header的部分,那么你就必须在你的Active Server
            Pages的任何输出语句之前进行这个脚本的操作,或者使用Buffer输出,(参看14章的有关小节)。
            前面的脚本是创建一个Cookie的简单示例,只是使用了最常用的Expires属性,其实还有许多其他属性也可以自行设置,下面是一个比较完全的例子:
            <%
            Response.Cookies(“Username”)=”Steve Jobs”
            Response.Cookies(“Username”).Expires=”Jan 1, 1999”
            Response.Cookies(“Username”).Path=”/examples”
            Response.Cookies(“Username”).Domain=”aspsite.com”
            Response.Cookies(“Username”).Secure=True
            %>
            这个脚本例子和前面的其实没有什么区别,不过有三个附加的属性需要解释:
            ■Path属性是用来更加严格的限定浏览器发送Cookie,在这个例子中,只有针对于
            /examples目录的请求的Header中才携带Cookie信息,例如/examples/hello.asp以及
            /examples/chapter16/hello.asp的请求都会在Header上携带Cookie信息,但是如果是浏览器对/hello.asp的请求就不会携带该Cookie信息。Path属性的默认值是该Cookie创建的Active
            Server Pages所在的路径。(也就是说,即便不做指定,也不会跨过目 录发送Cookie)
            ■Domain属性,限定了Cookie发送的网站,例子中的aspsite.com说明cookie可以被发送到www.aspsite.com或者beetle.aspsite.com或者yeah.aspsite.com等等,同样作为默认值是该Cookie创建的网站。
            ■最后是Secure属性,顾名思义,该属性设为True则传递中就实行了加密算法,如果你正在使用安全接口层,那么你就可以使用这个属性(参见第二章,安装使用
            Internet Information Server)
            在一个Active Server Page中读取cookie,你只需要使用Request对象的Cookies集合,
            例如,输出一个cookie值,那么脚本如下:
            <%=Request.Cookies(“Username”) %>
            这个脚本将名字为Username的Cookie值进行了输出,和以前同样的是,你依然可以利用For
            Each循环或者利用Count属性和For …Next循环结合的方式来将Cookie集合
            的所有属性值显示出来,下面这个例子的运行结果应当无须解释了。
            <%
            For EACH thing IN Request.Cookies
            Response.write(“<BR>”&thing&Request.Cookies(thing))
            NEXT
            %>
            创建多个Cookie
            你当然还可以创建不止一个Cookie,只是在Response对象的Cookies集合中简单的定义多个名称就可以了。不过,许多浏览器对一个指定网站就限定了三到四个Cookie。
            创建多个Cookie还有一种选择,就是创建一个Cookie字典,那么一个Cookie字典中就可以含有多个键值对,下面是这么一个字典的例子:
            <%
            Response.Cookies(“User”)(“Name”)=”Bill Gates”
            Response.Cookies(“User”)(“Password”)=”billions”
            %>
            这个脚本创建了一个名为User的Cookie字典,其中含有两个键分别是Name和
            Password,当这么Cookie字典创建时,请求的Header中是这样的信息:
            Set-Cookie:User=Name=Bill+Gates&Password=billions
            一个名字为User的Cookie创建了,其中含有两个键值对,这意味着所有的键和相应的值都在一个大的Cookie中。
            接受这样的Cookie值,你还可以利用以前的Response对象的Cookies集合,既可以将其全部显示,(这样显示就是没有经过解码的Header中的源代码,也就是上面Header中的信息,这样一般都是用于调试工作)也可以按每一个键的相应名称显示相应值,如下例,无须解释结果:
            <%=Request.Cookies(“User”) %>
            <%=Request.Cookies(“User”)(“Name”)%>
            <%=Request.Cookies(“User”)(”Name”)%>
            注意
            利用Cookie技术传递诸如密码这样的信息要特别小心,因为一般说来,这种信息是未经加密的,当然,如果你的网站有安全接口层技术,也可以进行加密传输,但是在浏览器端该信息还是存放在文本文件中。
            如果希望知道一个Cookie是否是一个Cookie字典,可以用HasKeys属性,例如下面脚本如果返回值为True,那么就是一个Cookie字典。
            <%=Request.Cookies(“User”).HasKeys %>
            
            不利用Cookie来保持信息
            其实这部分也是老调重弹,前面章节已经介绍过QueryString字段的使用及接收,以及Form的接收,其实这两种手段也可以进行一些信息保存,最后我们会对这三种方案进行综合比较。
            利用QueryString来保持信息
            第15章中有关小节有所介绍,由于你可以在连接中添加任何QueryString字段,那么,只要你在网站的所有连接中添加一个保存用户某种信息的字段,再在各个程序上进行相应处理,就可以进行模拟的跟踪,如下例:
            <HTML>
            <HEAD><TITLE>Query字段进行信息保留</TITLE></HEAD>
            <BODY>
            <%
            Username=Server.URLEncode(“Bill Gates”)
            %>
            <A Href=../../”/nextpage.asp?<%=UserName%>”>点击这里</a>
            </BODY>
            </HTML>
            这个脚本将Bill
            Gates赋值给Username的变量,然后将它通过QueryString传递给nextpage.asp,那么在Nextpage.asp中你就可以接受然后继续进行这个参数的传递。例如:下面就是Nextpage.asp的一个示例:
            <HTML>
            <HEAD><TITLE>Next Page</TITLE></HEAD>
            <BODY>
            <%
            Username=Server.URLEncode(“Request.QueryString(“Username”))
            %>
            <A HREF=../../”/thirdpage.asp?<%=Username%>”>点击这里</a>
            </body>
            </html>
            这个优点是显然适用于任何浏览器,但是必须承认,这样传递来保存信息实在太麻烦了,所有的连接都要考虑到,每一个Active Server
            Pages都必须相应处理一下, 而且用户很可能‘一不小心’就溜出了这种跟踪之外。修改起来也过于麻烦。
            另一个缺点是针对不同的浏览器必须考虑长度限制,前面章节介绍过这种限制,现在有的浏览器对于过长是截取信息,有的则干脆报错,不过相信这都不是你所希望的。同时安全性没有保证。
            利用Form的hidden类型进行信息传递
            如果你确实需要传递大量信息而又不想选用Session变量,那么您别无选择只有利用Form的Hidden类型。正如下例:
            <HTML>
            <HEAD><TITLE>Form传参示例</TITLE></HEAD>
            <BODY>
            <%
            Username=”Bill Gates”
            %>
            <FORM METHOD=”Post” Action=”/nextpage.asp”>
            <INPUT Name=”Username” TYPE=”HIDDEN” VALUE=”<%=Username%>”>
            <input type=”submit” name=”下一页”>
            </Form>
            </Body>
            </HTML>
            这个主页包括一个HTML Form。其中有一个隐含类型名字为Username,
            同时赋予Username变量的值。这个Form也有一个Submit按钮。当按钮点击后,在hiden类型中存放的Username的值将传递到下一个主页上。在下一个主页进行处理,然后以同样方式传递到另外一个新的主页上,下面是nextpage.asp的例子:
            <HTML>
            <HEAD><TITLE>下一页</TITLE></HEAD>
            <BODY>
            <%
            Username=Request.Form(“Username”)
            %>
            <FORM METHOD=”Post” Action=”/thirdpage.asp”>
            <input name=”Username” Type=”hidden” Value=”<%=Username%>”>
            <input type=submit value=”再下一页”>
            </Form>
            </Body>
            </Html>
            方法结合
            这两种方法实现起来都十分麻烦而且颇为”费力不讨好”,但是,如果偏要不用Cookies和Session变量来传递信息,确实也别无良策。同时,这两种方法确实可以适用于任何浏览器。
            请注意,如果在任意一页中没有进行这种QueryString字段或者hidden类型的Form的处理,那么这种跟踪就停止了,不管这是你希望的还是程序上不小心造成的。
            注意
            一个十分显著的缺点是不管利用QueryString字段还是利用Hidden Form传递
            信息,安全性都是毫无保证的,这是由于浏览器对信息的接受是在几乎毫无屏障的情况下进行的。
            你完全可以将这两种方法结合起来,而在接受时可以没有任何区别,这里面补充的是,对于Response对象,可以不指定Form集合和QueryString集合来进行接受,这时系统会自动辨认。见下面这个例子:
            <HTML>
            <HEAD><TITLE>下一页</TITLE></HEAD>
            <BODY>
            <%
            Username=Request(“Username”)
            %>
            <!---注:就是上面这个脚本,QueryString和hidden的Form都可以正确接收--->
            <Form Method=”Post” Action=”/nextpage.asp”>
            <input name=”Username” Type=”Hidden” Value=”<%=Username%>”>
            <input type=Submit value=”下一页”>
            </FORM>
            <a href=/nextpage.asp?<%=ServerURLEncode(Username)%>点击这里</a>
            </BODY>
            </HTML>
            在这个例子中,变量Username被赋值而无须知道上一页是利用的Hidden form域
            还是QueryString来传递参数。在以后编制Active Server Pages时,这种
            Request(“Username”)形式的简易调用将十分常用。
            总结
            在这章里面,你应当学到了怎样利用Sessions进行信息处理,首先你学到的是创建一个Session和用它在多主页间存储和传递信息,同时你应当掌握在Session开始和结束时创建相应脚本程序,这样做对于进行统计太重要了。同时,你还学会了和Session密切相关的,创建和读取Cookies信息。最后,对于那些实在不愿意使用Session和Cookie的人们提供了一些替代手段的介绍和讨论。