一简介
Cookie 为 Web 应用程序保存用户相关信息提供了一种有用的方法例如当用户访问您的站点时您可以利用 Cookie 保存用户首选项或其他信息这样当用户下次再访问您的站点时应用程序就可以检索以前保存的信息
本文概要介绍 Cookie 在 ASPNET 应用程序中的应用为您展示在 ASPNET 中应用 Cookie 的技术细节例如编写 Cookie然后再读取它们同时还将为您介绍 Cookie 的各种特性和各种特殊情况以及 ASPNET 对 Cookie 的支持
二什么是 Cookie?
Cookie 是一小段文本信息伴随着用户请求和页面在 Web 服务器和浏览器之间传递用户每次访问站点时Web 应用程序都可以读取 Cookie 包含的信息
假设在用户请求访问您的网站 wwwcontosocom 上的某个页面时您的应用程序发送给该用户的不仅仅是一个页面还有一个包含日期和时间的 Cookie用户的浏览器在获得页面的同时还得到了这个 Cookie并且将它保存在用户硬盘上的某个文件夹中
以后如果该用户再次访问您站点上的页面当该用户输入 URL wwwcontosocom 时浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie如果该 Cookie 存在浏览器就将它与页面请求一起发送到您的站点您的应用程序就能确定该用户上一次访问站点的日期和时间您可以根据这些信息向用户发送一条消息也可以检查过期时间或执行其他有用的功能
Cookie 是与 Web 站点而不是与具体页面关联的所以无论用户请求浏览站点中的哪个页面浏览器和服务器都将交换 wwwcontosocom 的 Cookie 信息用户访问其他站点时每个站点都可能会向用户浏览器发送一个 Cookie而浏览器会将所有这些 Cookie 分别保存
以上就是 Cookie 的基本工作原理那么Cookie 有哪些用途呢?最根本的用途是 Cookie 能够帮助 Web 站点保存有关访问者的信息更概括地说Cookie 是一种保持 Web 应用程序连续性(即执行状态管理)的方法浏览器和 Web 服务器除了在短暂的实际信息交换阶段以外总是断开的而用户向 Web 服务器发送的每个请求都是单独处理的与其他所有请求无关然而在大多数情况下都有必要让 Web 服务器在您请求某个页面时对您进行识别例如购物站点上的 Web 服务器跟蹤每个购物者以便站点能够管理购物车和其他的用户相关信息因此 Cookie 的作用就类似于名片它提供了相关的标识信息可以帮助应用程序确定如何继续执行
使用 Cookie 能够达到多种目的所有这些目的都是为了使 Web 站点记住您例如一个实施民意测验的站点可以简单地利用 Cookie 作为布尔值表示您的浏览器是否已经参与了投票从而避免您重复投票 而那些要求用户登录的站点则可以通过 Cookie 来确定您是否已经登录过这样您就不必每次都输入凭据
有关 Cookie 的更多背景信息建议您阅读 Verizon Web 站点中的How Internet Cookies Work一文地址为 http://wwwverizoncom/about/community/learningcenter/articles/displayarticle/zhtml(英文)其作者详细解释了什么是 Cookie 以及 Cookie 是如何在浏览器和服务器之间交换信息的他还全面总结了 Cookie 涉及的隐私问题
顺便问一下您是否想知道它们为什么被称作Cookie?Jargon File(又称为The New Hackers Dictionary)版本 对这一术语的词源给出了准确的定义和合理的解释您可以在 http://wwwcatborg/~esr/jargon/jargonhtml#cookie(英文)找到相关的条目
在此后的内容中本文将假设您已经知道什么是 Cookie并且假设您已经清楚为什么要在 ASPNET 应用程序中使用 Cookie
三Cookie 的限制
在开始讨论 Cookie 的技术细节之前我想先介绍一下 Cookie 应用的几条限制大多数浏览器支持最多可达 字节的 Cookie如果要将为数不多的几个值保存到用户计算机上这一空间已经足够大但您不能用一个 Cookie 来保存数据集或其他大量数据在实际应用中您可能并不希望在 Cookie 中保存大量的用户信息而只希望保存用户编号或其他标识符之后当用户再次访问您的站点时您就可以使用该用户 ID 在数据库中查找用户的详细信息(有关保存用户信息的说明请参阅 Cookie 和安全性)
浏览器还限制了您的站点可以在用户计算机上保存的 Cookie 数大多数浏览器只允许每个站点保存 个 Cookie如果试图保存更多的 Cookie则最先保存的 Cookie 就会被删除还有些浏览器会对来自所有站点的 Cookie 总数作出限制这个限制通常为 个
您最可能遇到的 Cookie 限制是用户可以设置自己的浏览器拒绝接受 Cookie您很难解决这个问题除非完全不使用 Cookie 而是通过其他机制来保存用户相关信息保存用户信息的一种常用方法是会话状态但会话状态又依赖于 Cookie这一点在后面的 Cookie 和会话状态中阐述
注意有关状态管理和 Web 应用程序中用于保存信息的选项的详细信息请参阅 Introduction to Web Forms State(英文)和 State Management Recommendations(英文)
更一般的经验很可能是尽管 Cookie 在应用程序中非常有用应用程序也不应该依赖于能够保存 Cookie利用 Cookie 可以做到锦上添花但不要利用它们来支持关键功能如果您的应用程序必须使用 Cookie则您可以通过测试来确定浏览器是否接受 Cookie我在本文后面的检查浏览器是否接受 Cookie 一节中简单介绍了一种测试方法
四编写 Cookie
您可以利用页面的 Response(英文)属性来编写 Cookie该属性提供的对象使用户可以将信息添加到由页面向浏览器呈现的信息中Response 对象支持一个名为 Cookies(英文)的集合您可以向其中添加要写入浏览器的 Cookie
注意下面要讨论的 Response 对象和 Request 对象分别是包含 HttpResponse(英文)和 HttpRequest(英文)类实例的页面的属性要在文档中查找 Response 和 Request 的信息请参阅 HttpResponse 和 HttpRequest 下的内容
在创建 Cookie 时您需要指定几个值最初您要指定 Cookie 的名称和其中保存的值您可以创建多个 Cookie每个 Cookie 都必须具有唯一的名称以便日后读取时识别(Cookie 是按名称保存的所以如果您创建了两个名称相同的 Cookie后保存的那一个将覆盖前一个)
您可能还希望指定 Cookie 的过期日期和时间Cookie 一般都写入到用户的磁盘然后可能一直都留在磁盘上因此您可以指定 Cookie 过期的日期和时间当用户再次访问您的站点时浏览器会先检查您站点的 Cookie 集合如果某个 Cookie 已经过期浏览器不会把这个 Cookie 随页面请求一起发送给服务器而是删除这个已经过期的 Cookie(您的站点可能已经在用户计算机上写入了多个 Cookie每个 Cookie 都有各自的过期日期和时间) 请注意由浏览器负责管理硬盘上的 Cookie这将影响您在应用程序中对 Cookie 的使用我很快会介绍这方面的内容
一个 Cookie 的有效期应为多长?这取决于 Cookie 的用途换句话说取决于您的应用程序需要 Cookie 值保持有效的时间有多长如果利用 Cookie 统计网站的访问者您可以把有效期设置为 年如果某个用户已有一年时间未访问您的站点则可以把该用户当作新的访问者 如果利用 Cookie 来保存用户的首选项则可以把其设置为永远有效(例如 年后到期)因为定期重新设置首选项对用户而言是比较麻烦的有时您可能需要编写在数秒或数分钟内即过期的 Cookie在本文后面的检查浏览器是否接受 Cookie 一节中我列举了一个示例该示例中创建的 Cookie 的实际有效期就只有几秒
注意不要忘记用户随时可以删除自己计算机上的 Cookie所以即使您保存了长期有效的 Cookie用户也可以自行决定将其全部删除同时清除保存在 Cookie 中的所有设置
如果没有设置 Cookie 的有效期还是可以创建 Cookie但它不会保存到用户的硬盘上而是会成为用户会话信息的一部分如果用户关闭浏览器或会话超时该 Cookie 就会被删除这种非永久性的 Cookie 很适合用来保存只需短时间保存的信息或者保存由于安全原因不应该写入客户计算机磁盘的信息例如如果用户使用的是一台公用计算机而您不希望把 Cookie 写入这种计算机的磁盘上这时就可以使用非永久性的 Cookie
您可以通过多种方法把 Cookie 添加到 ResponseCookies 集合中以下示例介绍了两种完成此任务的方法
ResponseCookies(userName)Value = mike
ResponseCookies(userName)Expires = DateTimeNowAddDays()
Dim aCookie As New HttpCookie(lastVisit)
aCookieValue = DateTimeNowToString
aCookieExpires = DateTimeNowAddDays()
ResponseCookiesAdd(aCookie)
该示例向 Cookies 集合中添加了两个 Cookie一个称为userName另一个称为lastVisit对于第一个 Cookie我直接设置了 ResponseCookies 集合的值您可以使用这种方法向集合中添加值因为 ResponseCookies 是从 NameObjectCollectionBase(英文)类型的特殊集合派生得到的
对于第二个 Cookie我创建了 Cookie 对象的一个实例(HttpCookie [英文] 类型)并设置了其属性然后通过 Add 方法把它添加到 ResponseCookies 集合实例化 HttpCookie 对象时您必须把 Cookie 名称作为构造函数的一部分进行传递
这两个示例完成了相同的任务即向浏览器写入一个 Cookie您要采用哪种方法主要取决于您的个人喜好您可能会发现第二种方法在设置 Cookie 属性方面要稍微容易一些但同时您也会注意到两者的差别并不是很大
在这两种方法中有效期值必须为 DateTime 类型而lastVisited值也是日期/时间值但在这种情况下我必须把日期/时间值转换为字符串因为 Cookie 中的任何值最终都是以字符串的形式保存的
五查看您的 Cookie
您可能会发现了解创建 Cookie 的效果会对您很有帮助而查看 Cookie 是比较容易的因为它们都是文本文件关键在于您能找到它们不同的浏览器保存 Cookie 的方式也不同我将介绍 Internet Explorer 是如何保存 Cookie 的如果您使用的是其他浏览器请查看该浏览器的帮助以了解有关 Cookie 处理方面的知识
查看 Cookie 的一个简便方法是让 Internet Explorer 为您查找在 Internet Explorer 中从工具菜单中选择Internet 选项在常规选项卡中单击设置然后单击查看文件Internet Explorer 将打开一个窗口显示所有的临时文件包括 Cookie在窗口中查找以Cookie:开头的文件 或查找文本文件双击一个 Cookie在默认的文本文件中打开它
您也可以在硬盘上查找 Cookie 的文本文件从而打开 CookieInternet Explorer 将站点的 Cookie 保存在文件名格式为 @txt 的文件中其中 是您的帐户名例如如果您的名称为 mikepope您访问的站点为 wwwcontosocom那么该站点的 Cookie 将保存在名为 mikepope@wwwcontosotxt 的文件中(该文件名可能包含一个顺序的编号如 mikepope@wwwcontoso[]txt)
这个 Cookie 文本文件是与用户相关的所以会按照帐户分别保存例如在 Windows XP 中您可以在如下所示的目录中找到 Cookie 文件
c:\Documents and Settings\\Cookies
要查找最新创建的 Cookie可以按修改日期对目录内容进行排序并查找最近修改的文件
您可以使用文本编辑器打开 Cookie如果该文件包含多个 Cookie这些 Cookie 之间将用星号 (*) 分隔每个 Cookie 的第一行是 Cookie 的名称第二行是值其余各行则包含 Cookie 的日常处理信息例如过期日期和时间Cookie 中还有一个简单的校验和如果更改 Cookie 名称或值的长度浏览器就会检测到修改并删除该 Cookie
六多值 Cookie(子键)
以上示例为每个要保存的值(用户名上次访问时间)都使用了一个 Cookie 您也可以在一个 Cookie 中保存多个名称/值对名称/值对也称作键或子键具体取决于您读取的内容(如果您熟悉 URL 的结构就会发现子键与其中的查询字符串非常相象) 例如如果不希望创建名为userName和lastVisit的两个单独的 Cookie可以创建一个名为userInfo的 Cookie并使其包含两个子键userName和lastVisit
有很多原因会让我们用子键来代替单独的 Cookie最显而易见的是把相关或类似的信息放在一个 Cookie 中会比较有条理另外由于所有信息都在一个 Cookie 中所以诸如有效期之类的 Cookie 属性就适用于所有信息(当然如果要为不同类型的信息指定不同的过期日期就应该把信息保存在单独的 Cookie 中)
带有子键的 Cookie 还可以帮助您减小 Cookie 的大小如前面的 Cookie 的限制一节所述Cookie 的总大小限制在 字节以内而且不能为一个网站保存超过 个 Cookie利用带子键的单个 Cookie站点的 Cookie 数量就不会超过 个的限制此外一个 Cookie 会占用大约 个字符的基本空间开销(用于保存有效期信息等)再加上其中保存的值的长度其总和接近 K 的限制如果使用五个子键而不是五个单独的 Cookie您可以省去四个 Cookie 的基本空间开销总共能节省大约 个字节
要创建带子键的 Cookie您可以使用用于编写单个 Cookie 的各种语法以下示例显示了编写同一 Cookie 的两种不同方法其中的每个 Cookie 都带有两个子键
ResponseCookies(userInfo)(userName) = mike
ResponseCookies(userInfo)(lastVisit) = DateTimeNowToString
ResponseCookies(userInfo)Expires = DateTimeNowAddDays()
Dim aCookie As New HttpCookie(userInfo)
aCookieValues(userName) = mike
aCookieValues(lastVisit) = DateTimeNowToString
aCookieExpires = DateTimeNowAddDays()
ResponseCookiesAdd(aCookie)
七控制 Cookie 有效范围
默认情况下一个站点的全部 Cookie 都一起保存在客户机上而且所有这些 Cookie 都会随着对该站点发送的请求一起发送到服务器也就是说站点的每个页面都能得到该站点的所有 Cookie但有时候您可能希望 Cookie 更具有针对性这时您可以通过两种方法设置 Cookie 的有效范围
·把 Cookie 的有效范围限制在服务器上的一个文件夹中实际上这样就将 Cookie 限制到站点上的某个应用程序
·把有效范围设置为某个域从而允许您指定域中的哪些子域可以访问 Cookie
1将 Cookie 限制到某个文件夹或应用程序
要将 Cookie 限制到服务器上的某个文件夹请按如下方法设置 Cookie 的 Path 属性
Dim appCookie As New HttpCookie(AppCookie)
appCookieValue = written & NowToString
appCookieExpires = NowAddDays()
appCookiePath = /Application
ResponseCookiesAdd(appCookie)
当然您也可以通过直接设置 ResponseCookies 来编写 Cookie如前文所述
路径可以是站点根目录下的物理路径也可以是虚拟根目录这样一来Cookie 就只能用于 Application 文件夹或虚拟根目录中的页面例如如果您的站点名为 wwwcontosocom则前面示例中生成的 Cookie 就只能用于路径为 http://wwwcontosocom/Application/ 的页面以及该文件夹下的所有页面而不适用于其他应用程序中的页面如 http://wwwcontosocom/Application/ 或 http://wwwcontosocom/ 下的页面
提示通过对 Internet Explorer 和 Mozilla 浏览器进行测试发现此处使用的路径是区分大小写的一般而言Windows 服务器上的 URL 不区分大小写但这种情况例外您无法控制用户如何在浏览器中输入 URL但是如果您的应用程序依赖于与特定路径相关的 Cookie则请确保您所创建的所有超链接中的 URL 与 Path 属性值的大小写相匹配
2将Cookie 的有效范围限制到域
默认情况下Cookie 与特定的域相关联例如如果您的站点是 wwwcontosocom那么当用户向该站点请求页面时您编写的 Cookie 就被发送到服务器(有特定路径值的 Cookie 除外我在上一节刚刚解释过) 如果您的站点有子域(例如 contosocomsalescontosocom 和 supportcontosocom)就可以把 Cookie 同特定的子域相关联为此需要设置 Cookie 的 Domain 属性如下所示
ResponseCookies(domain)Value = DateTimeNowToString
ResponseCookies(domain)Expires = DateTimeNowAddDays()
ResponseCookies(domain)Domain = supportcontosocom
如果按照这种方式设置域则 Cookie 只能用于指定子域中的页面
您也可以利用 Domain 属性来创建可在多个子域中共享的 Cookie例如对域进行如下设置
ResponseCookies(domain)Value = DateTimeNowToString
ResponseCookies(domain)Expires = DateTimeNowAddDays()
ResponseCookies(domain)Domain = contosocom
这样该 Cookie 就可用于主域salescontosocom 和 supportcontosocom