<<<返回

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”)形式的简易调用将十分常用。