细说Cookie

Cookie虽然是个很简单的东西,但它又是WEB开发中一个很重要的客户端数据来源,而且它可以实现扩展性很好的会话状态, 所以我认为每个WEB开发人员都有必要对它有个清晰的认识。本文将对Cookie这个话题做一个全面的描述, 也算是本人对Cookie的认识总结。

Cookie 概述

Cookie是什么? Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息。

为什么需要Cookie? 因为HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分 是不是来源于同一个浏览器。所以,需要额外的数据用于维护会话。 Cookie 正是这样的一段随HTTP请求一起被传递的额外数据。

Cookie能做什么? Cookie只是一段文本,所以它只能保存字符串。而且浏览器对它有大小限制以及 它会随着每次请求被发送到服务器,所以应该保证它不要太大。 Cookie的内容也是明文保存的,有些浏览器提供界面修改,所以, 不适合保存重要的或者涉及隐私的内容。

Cookie 的限制。 大多数浏览器支持最大为 4096 字节的 Cookie。由于这限制了 Cookie 的大小,最好用 Cookie 来存储少量数据,或者存储用户 ID 之类的标识符。用户 ID 随后便可用于标识用户,以及从数据库或其他数据源中读取用户信息。 浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。

通过前面的内容,我们了解到Cookie是用于维持服务端会话状态的,通常由服务端写入,在后续请求中,供服务端读取。 下面本文将按这个过程看看Cookie是如何从服务端写入,最后如何传到服务端以及如何读取的。

Cookie的写、读过程

在Asp.net中,读写Cookie是通过使用HttpCookie类来完成的,它的定义如下:

public sealed class HttpCookie
{
    
// 获取或设置将此 Cookie 与其关联的域。默认值为当前域。
    public string Domain { getset; }
    
// 获取或设置此 Cookie 的过期日期和时间(在客户端)。
    public DateTime Expires { getset; }
    
// 获取一个值,通过该值指示 Cookie 是否具有子键。
    public bool HasKeys { get; }
    
// 获取或设置一个值,该值指定 Cookie 是否可通过客户端脚本访问。
    
// 如果 Cookie 具有 HttpOnly 属性且不能通过客户端脚本访问,则为 true;否则为 false。默认为 false。
    public bool HttpOnly { getset; }
    
// 获取或设置 Cookie 的名称。
    public string Name { getset; }
    
// 获取或设置要与当前 Cookie 一起传输的虚拟路径。默认值为当前请求的路径。
    public string Path { getset; }
    
// 获取或设置一个值,该值指示是否使用安全套接字层 (SSL)(即仅通过 HTTPS)传输 Cookie。
    public bool Secure { getset; }
    
// 获取或设置单个 Cookie 值。默认值为空引用。
    public string Value { getset; }
    
// 获取单个 Cookie 对象所包含的键值对的集合。
    public NameValueCollection Values { get; }
    
// 获取 System.Web.HttpCookie.Values 属性的快捷方式。
    public string this[string key] { getset; }
}

Cookie写入浏览器的过程:我们可以使用如下代码在Asp.net项目中写一个Cookie 并发送到客户端的浏览器(为了简单我没有设置其它属性)。

/// <summary>
/// 用于方便使用Cookie的扩展工具类
/// </summary>
public static class CookieExtension
{
    
// 我们可以为一些使用频率高的类型写专门的【读取】方法

    
/// <summary>
    
/// 从一个Cookie中读取字符串值。
    
/// </summary>
    
/// <param name="cookie"></param>
    
/// <returns></returns>
    public static string GetString(this HttpCookie cookie)
    {
        
if( cookie == null )
            
return null;

        
return cookie.Value;
    }

    
/// <summary>
    
/// 从一个Cookie中读取 Int 值。
    
/// </summary>
    
/// <param name="cookie"></param>
    
/// <param name="defaultVal"></param>
    
/// <returns></returns>
    public static int ToInt(this HttpCookie cookie, int defaultVal)
    {
        
if( cookie == null )
            
return defaultVal;

        
return cookie.Value.TryToInt(defaultVal);
    }

    
/// <summary>
    
/// 从一个Cookie中读取值并转成指定的类型
    
/// </summary>
    
/// <typeparam name="T"></typeparam>
    
/// <param name="cookie"></param>
    
/// <returns></returns>
    public static T ConverTo<T>(this HttpCookie cookie)
    {
        
if( cookie == null )
            
return default(T);

        
return (T)Convert.ChangeType(cookie.Value, typeof(T));
    }

    
/// <summary>
    
/// 从一个Cookie中读取【JSON字符串】值并反序列化成一个对象,用于读取复杂对象
    
/// </summary>
    
/// <typeparam name="T"></typeparam>
    
/// <param name="cookie"></param>
    
/// <returns></returns>
    public static T FromJson<T>(this HttpCookie cookie)
    {
        
if( cookie == null )
            
return default(T);

        
return cookie.Value.FromJson<T>();
    }


    
/// <summary>
    
/// 将一个对象写入到Cookie
    
/// </summary>
    
/// <param name="obj"></param>
    
/// <param name="name"></param>
    
/// <param name="expries"></param>
    public static void WriteCookie(this object obj, string name, DateTime? expries)
    {
        
if( obj == null )
            
throw new ArgumentNullException("obj");

        
ifstring.IsNullOrEmpty(name) )
            
throw new ArgumentNullException("name");
        

        HttpCookie cookie 
= new HttpCookie(name, obj.ToString());

        
if( expries.HasValue )
            cookie.Expires 
= expries.Value;

        HttpContext.Current.Response.Cookies.Add(cookie);
    }

    
/// <summary>
    
/// 删除指定的Cookie
    
/// </summary>
    
/// <param name="name"></param>
    public static void DeleteCookie(string name)
    {
        
ifstring.IsNullOrEmpty(name) )
            
throw new ArgumentNullException("name");

        HttpCookie cookie 
= new HttpCookie(name);

        
// 删除Cookie,其实就是设置一个【过期的日期】
        cookie.Expires = new DateTime(190011);
        HttpContext.Current.Response.Cookies.Add(cookie);
    }
}
public static class MyExtension
{
    
/// <summary>
    
/// 将一个字符串转成为一个整数,如果转换失败,返回 0
    
/// </summary>
    
/// <param name="str"></param>
    
/// <returns></returns>
    public static int TryToInt(this string str)
    {
        
return TryToInt(str, 0);
    }

    
/// <summary>
    
/// 将一个字符串转成为一个整数,可指定默认值。
    
/// </summary>
    
/// <param name="str"></param>
    
/// <param name="defaultVal"></param>
    
/// <returns></returns>
    public static int TryToInt(this string str, int defaultVal)
    {
        
int result = defaultVal;
        
int.TryParse(str, out result);
        
return result;
    }


    
/// <summary>
    
/// 将一个对象序列化成 JSON 格式字符串
    
/// </summary>
    
/// <param name="obj"></param>
    
/// <returns></returns>
    public static string ToJson(this object obj)
    {
        
if( obj == null )
            
return string.Empty;

        JavaScriptSerializer jss 
= new JavaScriptSerializer();
        
return jss.Serialize(obj);
    }

    
/// <summary>
    
/// 从JSON字符串中反序列化对象
    
/// </summary>
    
/// <typeparam name="T"></typeparam>
    
/// <param name="cookie"></param>
    
/// <returns></returns>
    public static T FromJson<T>(this string cookie)
    {
        
ifstring.IsNullOrEmpty(cookie) )
            
return default(T);

        JavaScriptSerializer jss 
= new JavaScriptSerializer();
        
return jss.Deserialize<T>(cookie);
    }

}
public static class TestClass
{
    
public static void Write()
    {
        
string str = "中国";
        
int aa = 25;
        DisplaySettings setting 
= new DisplaySettings { Style = 3, Size = 50 };
        DateTime dt 
= new DateTime(2012111200);

        str.WriteCookie(
"Key1", DateTime.Now.AddDays(1d));
        aa.WriteCookie(
"Key2"null);
        setting.ToJson().WriteCookie(
"Key3"null);
        dt.WriteCookie(
"Key4"null);
    }

    
public static void Read()
    {
        HttpRequest request 
= HttpContext.Current.Request;

        
string str = request.Cookies["Key1"].GetString();
        
int num = request.Cookies["Key2"].ToInt(0);
        DisplaySettings setting 
= request.Cookies["Key3"].FromJson<DisplaySettings>();
        DateTime dt 
= request.Cookies["Key4"].ConverTo<DateTime>();
    }    
}



public static class CookieValues
{
    
// 建议把Cookie相关的参数放在一起,提供 get / set 属性(或者方法)来访问,以避免"key"到处乱写

    
public static string AAA
    {
        
get { return HttpContext.Current.Request.Cookies["Key1"].GetString(); }
    }
    
public static int BBB
    {
        
get { return HttpContext.Current.Request.Cookies["Key2"].ToInt(0); }
    }
    
public static DisplaySettings CCC
    {
        
get { return HttpContext.Current.Request.Cookies["Key3"].FromJson<DisplaySettings>(); }
    }
    
public static DateTime DDD
    {
        
get { return HttpContext.Current.Request.Cookies["Key4"].ConverTo<DateTime>(); }
    }
}

 【转自--http://www.cnblogs.com/fish-li/archive/2011/07/03/2096903.html】

原文地址:https://www.cnblogs.com/jasonoiu/p/Elaborate_Cookies.html