开始学习ASP.NET的时候就学习Cookie,感觉用法很简单。之后的项目中发现Cookie的用处和用法还是很多,很广的。例如:单点登录SSO。
我在写这文章之前也参考了网上的一些资料。主要还是MSDN上资料,就是总结一下对自己有帮助的吧。
一:概念
Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息。
例如,如果在用户请求站点中的页面时应用程序发送给该用户的不仅仅是一个页面,还有一个包含日期和时间的 Cookie,用户的浏览器在获得页面的同时还获得了该 Cookie,并将它存储在用户硬盘上的某个文件夹中。
以后,如果该用户再次请求您站点中的页面,当该用户输入 URL 时,浏览器便会在本地硬盘上查找与该 URL 关联的 Cookie。如果该 Cookie 存在,浏览器便将该 Cookie 与页请求一起发送到您的站点。然后,应用程序便可以确定该用户上次访问站点的日期和时间。您可以使用这些信息向用户显示一条消息,也可以检查到期日期。
Cookie 与网站关联,而不是与特定的页面关联。因此,无论用户请求站点中的哪一个页面,浏览器和服务器都将交换 Cookie 信息。用户访问不同站点时,各个站点都可能会向用户的浏览器发送一个 Cookie;浏览器会分别存储所有 Cookie。
Cookie 帮助网站存储有关访问者的信息。一般来说,Cookie 是一种保持 Web 应用程序连续性(即执行状态管理)的方法。除短暂的实际交换信息的时间外,浏览器和 Web 服务器间都是断开连接的。对于用户向 Web 服务器发出的每个请求,Web 服务器都会单独处理。但是在很多情况下,Web 服务器在用户请求页时识别出用户会十分有用。例如,购物站点上的 Web 服务器跟踪每位购物者,这样站点就可以管理购物车和其他的用户特定信息。因此,Cookie 可以作为一种名片,提供相关的标识信息帮助应用程序确定如何继续执行。
使用 Cookie 能够达到多种目的,所有这些目的都是为了帮助网站记住用户。例如,一个实施民意测验的站点可以简单地将 Cookie 作为一个 Boolean 值,用它来指示用户的浏览器是否已参与了投票,这样用户便无法进行第二次投票。要求用户登录的站点则可以通过 Cookie 来记录用户已经登录,这样用户就不必每次都输入凭据。
二:Cookie 的限制
大多数浏览器支持最大为 4096 字节的 Cookie。由于这限制了 Cookie 的大小,最好用 Cookie 来存储少量数据,或者存储用户 ID 之类的标识符。用户 ID 随后便可用于标识用户,以及从数据库或其他数据源中读取用户信息。(有关存储用户信息安全建议的信息,请参见下面的“Cookie 和安全性”一节。)
浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。
通过前面的内容,我们了解到Cookie是用于维持服务端会话状态的,通常由服务端写入,在后续请求中,供服务端读取。下面本文将按这个过程看看Cookie是如何从服务端写入,最后如何传到服务端以及如何读取的。
三:Cookie相关操作
(1)编写Cookie
两种方式
Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);
HttpCookie aCookie = new HttpCookie("lastVisit");
aCookie.Value = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
(2) 多值Cookie
Response.Cookies["userInfo"]["userName"] = "patrick"; Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString(); Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1); HttpCookie aCookie = new HttpCookie("userInfo"); aCookie.Values["userName"] = "patrick"; aCookie.Values["lastVisit"] = DateTime.Now.ToString(); aCookie.Expires = DateTime.Now.AddDays(1); Response.Cookies.Add(aCookie);
(3)控制Cookie
若要将 Cookie 限制到服务器上的某个文件夹,请按下面的示例设置 Cookie 的 Path 属性:
HttpCookie appCookie = new HttpCookie("AppCookie"); appCookie.Value = "written " + DateTime.Now.ToString(); appCookie.Expires = DateTime.Now.AddDays(1); appCookie.Path = "/Application1"; Response.Cookies.Add(appCookie);
(4)限制Cookie的域范围
默认情况下,Cookie 与特定域关联。例如,如果您的站点是 www.contoso.com,那么当用户向该站点请求任何页时,您编写的 Cookie 就会被发送到服务器。(这可能不包括带有特定路径值的 Cookie。)如果站点具有子域(例如,contoso.com、sales.contoso.com 和 support.contoso.com),则可以将 Cookie 与特定的子域关联。若要执行此操作,请设置 Cookie 的 Domain 属性,如此示例所示:
Response.Cookies["domain"].Value = DateTime.Now.ToString(); Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1); Response.Cookies["domain"].Domain = "support.contoso.com";
以此方式设置域时,Cookie 将仅可用于指定的子域中的页面。还可以使用 Domain 属性创建可在多个子域间共享的 Cookie,如下面的示例所示:
Response.Cookies["domain"].Value = DateTime.Now.ToString(); Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1); Response.Cookies["domain"].Domain = "contoso.com";
随后 Cookie 将可用于主域,也可用于 sales.contoso.com 和 support.contoso.com 域。
(5)修改和删除Cookie
不能直接修改 Cookie。更改 Cookie 的过程涉及创建一个具有新值的新 Cookie,然后将其发送到浏览器来覆盖客户端上的旧版本 Cookie。下面的代码示例演示如何更改存储用户对站点的访问次数的 Cookie 的值:
int counter;
if (Request.Cookies["counter"] == null) counter = 0; else
{
counter = int.Parse(Request.Cookies["counter"].Value);
}
counter++;
Response.Cookies["counter"].Value = counter.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);
删除 Cookie(即从用户的硬盘中物理移除 Cookie)是修改 Cookie 的一种形式。由于 Cookie 在用户的计算机中,因此无法将其直接移除。但是,可以让浏览器来为您删除 Cookie。该技术是创建一个与要删除的 Cookie 同名的新 Cookie,并将该 Cookie 的到期日期设置为早于当前日期的某个日期。当浏览器检查 Cookie 的到期日期时,浏览器便会丢弃这个现已过期的 Cookie。下面的代码示例演示删除应用程序中所有可用 Cookie 的一种方法:
HttpCookie aCookie; string cookieName; int limit = Request.Cookies.Count; for (int i=0; i<limit; i++) { cookieName = Request.Cookies[i].Name; aCookie = new HttpCookie(cookieName); aCookie.Expires = DateTime.Now.AddDays(-1); Response.Cookies.Add(aCookie); }
(6)判断浏览器是否接受Cookie
protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { if (Request.QueryString["AcceptsCookies"] == null) { Response.Cookies["TestCookie"].Value = "ok"; Response.Cookies["TestCookie"].Expires = DateTime.Now.AddMinutes(1); Response.Redirect("TestForCookies.aspx?redirect=" + Server.UrlEncode(Request.Url.ToString())); } else { Label1.Text = "Accept cookies = " + Server.UrlEncode( Request.QueryString["AcceptsCookies"]); } } }
以上来源于MSDN。主要是MSDN是一本真正的教科书呀。接下来,我就讲一下自己累到的一些问题和疑问
(7)上面都是在服务器端设置Cookie的。那么在客户端如何实现呢?
<script type="text/javascript">
function writeCookie() {
document.cookie = "userId=828;";
document.cookie = "userName=828;";
}
function readCookies() {
alert(document.cookie);
}
</script>
执行代码可以看出。
每个Cookie的键值对用;分隔,你还得去拆分进行处理。比较麻烦。所以要用Jquery插件jquery.cookie.js来进行客户端Cookie的操作。
四:疑问、解答
(1)会话cookie和持久cookie的区别
如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie,会话cookie一般不保存在硬盘上而是保存在内存里。
如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
怎么理解呢??
咱们用Firefox浏览器查看一下到底什么意思
先建立一个测试用例
/// 会话Cookie
protected void btnOne_Click(object sender, EventArgs e)
{
HttpCookie httpCookie = new HttpCookie("keyOne", "NoCookie");
Response.Cookies.Add(httpCookie);
}
//持久Cookie
protected void btnTwo_Click(object sender, EventArgs e)
{
HttpCookie httpCookie = FormsAuthentication.GetAuthCookie("User1", true);
httpCookie.Name = "keyTwo";
httpCookie.Value = "YewCookie";
httpCookie.Expires.AddSeconds(120);
Response.Cookies.Add(httpCookie);
}
当两个按扭都点击完成后,通过FireFox的插件(Web Developer 1.1.9)自带的功能可以查看Cookie信息。
如下图所示
一看就知道了吧。
当你关闭浏览器时,非持久性的Cookie是否丢失还要看浏览器的不同不会产生不一样的结果。
例如firefox吧。你无论打开多少个新窗口,它在在资源管理器中只有一个进程,如下图
IE则不同,每打开一个新的窗口,它就新产生一个IEXPLORE.EXE进程,如下图所示
结论:如果Cookie是非持久的,对于firefox来说需要关闭所有firefox的浏览器窗口,它的非持久Cookie才会丢失。因为上图可以看出firefox.exe只有一个,Cookie就在这一个进程中存储。
而对于IE来说。只需要关闭当前操作页面的窗口即可。
(2) cookie和session有什么关系呢??
这又该从Http协议说起了。因为http协议是无状态的。对于一个浏览器发出的请求,Web服务器无法区别是哪个浏览器发起的。所以为解决浏览器和服务器之间的会话问题。就得需要Cookie配合一下了。服务器把一个会话标识的ID保存到浏览器,而Cookie就成接受了这个工作。工作的内容是Web服务器让我保存一个会话标识ID,我就保存,并且在浏览器向服务器再次发请求时,会把Cookie放在Http请求头中一起发送到Web服务器。Web服务器根据Cookie发送的会话ID,就知道是哪个浏览器/客户端发的请求了。可以用Fiddler2工具查看。这个工具对开发者来说很有用呀。我就不多说这个工具怎么用了。先给个Fiddler2下载
好了。我们说一下Cookie和Sesion到底有什么关系。编写代码
protected void btnSession_Click(object sender, EventArgs e)
{
Session["app_ID"] = "test";
}
执行后,查看一下Cookie,结果如下
结果在浏览器中多了一个Cookie,这个就是保存Session会话ID的。
如果你还不信就继续代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
if (Session["app_ID"] != null)
{
Response.Write("会话ID存在");
}
else
{
Response.Write("会话ID不存在");
}
}
你第一次执行应该结果是:会话ID存在,你通过firefox的插件Fiddler2删除Cookie,再点击一次,结果不用多说了吧。
有人说这个Cookie的名称真难记。不如自己命名算了。还好记还好用。如果你想这样做,只需要在配置文件中指出它的名称即可,配制如下:
<sessionState cookieName="SessionToCookieID"></sessionState>
不信,你再试试上面的代码,保存到客户的会话ID是不是你设置的名称(SessionToCookieID)
最后附上测试用例代码:
1 <html xmlns="http://www.w3.org/1999/xhtml" > 2 <head runat="server"> 3 <title>设置Cookie</title> 4 <script type="text/javascript"> 5 function writeCookie() { 6 document.cookie = "userId=828;"; 7 document.cookie = "userName=828;"; 8 } 9 function readCookies() { 10 alert(document.cookie); 11 } 12 </script> 13 </head> 14 <body> 15 <form id="form1" runat="server"> 16 <div> 17 <asp:Button runat="server" ID="btnOne" Text="会话Cookie" onclick="btnOne_Click" /> 18 19 <asp:Button runat="server" ID="btnTwo" Text="持久cookie" onclick="btnTwo_Click" /> 20 21 <asp:Button runat="server" ID="btnDeleteCookie" Text="删除所有Cookie" 22 onclick="btnDeleteCookie_Click" /> 23 24 <asp:Button runat="server" ID="btnSession" Text="设置Session" 25 onclick="btnSession_Click" /> 26 27 <asp:Button ID="Button1" runat="server" Text="读取Session" 28 onclick="Button1_Click" /> 29 <br /> 30 31 <input type="button" id="btnClientWriteCookie" value="客户端写Cookie" onclick="writeCookie()" /> 32 <input type="button" id = "btnClientReadCookie" value = "客户端读Cookie" onclick ="readCookies()" /> 33 </div> 34 </form> 35 </body> 36 </html>
后台:
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 4 } 5 /// 会话Cookie 6 protected void btnOne_Click(object sender, EventArgs e) 7 { 8 HttpCookie httpCookie = new HttpCookie("keyOne", "NoCookie"); 9 Response.Cookies.Add(httpCookie); 10 } 11 //持久Cookie 12 protected void btnTwo_Click(object sender, EventArgs e) 13 { 14 HttpCookie httpCookie = FormsAuthentication.GetAuthCookie("User1", true); 15 16 httpCookie.Name = "keyTwo"; 17 httpCookie.Value = "YewCookie"; 18 httpCookie.Expires.AddSeconds(120); 19 20 21 Response.Cookies.Add(httpCookie); 22 } 23 24 protected void btnDeleteCookie_Click(object sender, EventArgs e) 25 { 26 HttpCookie cookie = new HttpCookie("keyOne", null); 27 cookie.Expires = new DateTime(1900, 1, 1); 28 Response.Cookies.Add(cookie); 29 30 HttpCookie cookie1 = new HttpCookie("keyTwo", null); 31 cookie1.Expires = new DateTime(1900, 1, 1); 32 Response.Cookies.Add(cookie1); 33 34 35 } 36 37 protected void btnSession_Click(object sender, EventArgs e) 38 { 39 Session["app_ID"] = "test"; 40 41 } 42 43 protected void Button1_Click(object sender, EventArgs e) 44 { 45 if (Session["app_ID"] != null) 46 { 47 Response.Write("会话ID存在"); 48 } 49 else 50 { 51 Response.Write("会话ID不存在"); 52 } 53 }
补充:
持久COOKIE也可以用以下代码实现
1 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket( 2 2, "Admin", DateTime.Now, DateTime.Now.AddYears(1), false, string.Empty); 3 string str = FormsAuthentication.Encrypt(ticket); 4 5 6 7 HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, str); 8 9 cookie.Path = System.Web.Security.FormsAuthentication.FormsCookiePath; 10 cookie.Expires = System.DateTime.Now.AddYears(100); 11 12 13 14 Response.Cookies.Add(cookie);
今天就写到这。后续还会有Cookie的相关操作,例如:jquery.cookie.js插件写Cookie,利用Cookie进行身份验证等等内容。
转载的请注原创地址,谢谢。