Fork me on GitHub

ASP.NET中的COOKIE

最近用到Cookie的历史记录浏览功能,小结一下吧。由于HTTP协议是无状态的,WEB服务端处理完一次请求后,因此即使同一次会话,服务端也无法识别,为了维护会话的状态,ASP.NET WEB模型提供了几种方式。一般有如下几种方式

基于表单提交(包括隐藏域)或者URL参数
基于Cookie
基于Session
基于ViewState

这里先只说Cookie的一些知识,Cookies是一种客户端技术,可以跟随请求之间携带数据以达到共享数据的目的,因此Cookie本身的大小与个数都是有限制的,因为Cookie使用HTTP请求头和响应头进行发送和接受,因此是一种服务器无关的技术。

存储与读写

.NET中读取Cookie很简单

// 摘要:
    //     提供创建和操作各 HTTP Cookie 的类型安全方法。
    public sealed class HttpCookie
    {
        // 摘要:
        //     创建并命名新的 Cookie。
        //
        // 参数:
        //   name:
        //     新 Cookie 的名称。
        public HttpCookie(string name);
        //
        // 摘要:
        //     创建和命名新的 Cookie,并为其赋值。
        //
        // 参数:
        //   name:
        //     新 Cookie 的名称。
        //
        //   value:
        //     新 Cookie 的值。
        public HttpCookie(string name, string value);

        // 摘要:
        //     获取或设置将此 Cookie 与其关联的域。
        //
        // 返回结果:
        //     要将此 Cookie 与其关联的域名。 默认值为当前域。
        public string Domain { get; set; }
        //
        // 摘要:
        //     获取或设置此 Cookie 的过期日期和时间。
        //
        // 返回结果:
        //     此 Cookie 的过期时间(在客户端)。
        public DateTime Expires { get; set; }
        //
        // 摘要:
        //     获取一个值,通过该值指示 Cookie 是否具有子键。
        //
        // 返回结果:
        //     如果 Cookie 具有子键,则为 true;否则为 false。 默认值为 false。
        public bool HasKeys { get; }
        //
        // 摘要:
        //     获取或设置一个值,该值指定 Cookie 是否可通过客户端脚本访问。
        //
        // 返回结果:
        //     如果 Cookie 具有 HttpOnly 特性且不能通过客户端脚本访问,则为 true;否则为 false。 默认值为 false。
        public bool HttpOnly { get; set; }
        //
        // 摘要:
        //     获取或设置 Cookie 的名称。
        //
        // 返回结果:
        //     除非构造函数另外指定,否则默认值为 null 引用(在 Visual Basic 中为 Nothing)。
        public string Name { get; set; }
        //
        // 摘要:
        //     获取或设置要与当前 Cookie 一起传输的虚拟路径。
        //
        // 返回结果:
        //     要与此 Cookie 一起传输的虚拟路径。 默认为 /,也就是服务器根目录。
        public string Path { get; set; }
        //
        // 摘要:
        //     获取或设置一个值,该值指示是否使用安全套接字层 (SSL)(即仅通过 HTTPS)传输 Cookie。
        //
        // 返回结果:
        //     如果通过 SSL 连接 (HTTPS) 传输 Cookie,则为 true;否则为 false。 默认值为 false。
        public bool Secure { get; set; }
        //
        // 摘要:
        //     确定 cookie 是否允许参与输出缓存。
        //
        // 返回结果:
        //     指定的true 输出缓存不会给出包含一个或多个对外 cookie 的 System.Web.HttpResponse 取消;否则 false。
        public bool Shareable { get; set; }
        //
        // 摘要:
        //     获取或设置单个 Cookie 值。
        //
        // 返回结果:
        //     Cookie 的值。 默认值为 null 引用(在 Visual Basic 中为 Nothing)。
        public string Value { get; set; }
        //
        // 摘要:
        //     获取单个 Cookie 对象所包含的键值对的集合。
        //
        // 返回结果:
        //     Cookie 值的集合。
        public NameValueCollection Values { get; }

        // 摘要:
        //     获取 System.Web.HttpCookie.Values 属性的快捷方式。 此属性是为了与以前的 Active Server Pages (ASP)
        //     版本兼容而提供的。
        //
        // 参数:
        //   key:
        //     Cookie 值的键(索引)。
        //
        // 返回结果:
        //     Cookie 值。
        public string this[string key] { get; set; }
    }

代码如下

            HttpCookie httpCookie = new HttpCookie("userName", "I'am Irving");
            httpCookie.HttpOnly = true;
            Response.Cookies.Set(httpCookie);

image

默认cookie的有效期是会话级别的,当然也可以设置时间,如票据的有效期,Cookies是保存在用户的本地机器上,不同的浏览器存储在不同的文件夹中,并且按照域名分别保存。即网站之间的Cookies不会彼此覆盖。如果我们设置了Cookies的有效期,那么就会存储在用户磁盘上,有下次有请求是来自此域下的path匹配,Cookies就会跟随HTTP报文一同发送给服务端。

可以使用HttpCookieCollection获得请求的所有Cookie

            StringBuilder sb = new StringBuilder(255);
            if (Response.Cookies["userName"] != null)
            {
                HttpCookieCollection cookies = Request.Cookies;
                for (int i = 0; i < cookies.Count; i++)
                {
                    sb.Append("Name: " + cookies[i].Name + "<br/>");
                    sb.Append("Expires: " + cookies[i].Expires.ToString() + "<br/>");
                    Response.Write(sb.ToString());
                }
            }
            else
            {
                HttpCookie httpCookie = new HttpCookie("userName", "I'am Irving");
                httpCookie.HttpOnly = true;
                httpCookie.Expires = DateTime.Now.AddDays(1);
                Response.Cookies.Add(httpCookie);
            }

Cookie的Path默认为根路径,可以手动设置当前cookie对哪些路径有效,已方便下次cookie跟随HTTP请求。

Cookies与Session的关系两者是密不可分的
对于Asp.Net而言,默认一次请求用到session会话,会默认生成一个默认名称为ASP.NET_SessionId的cookie用来标识当前的请求是来自一次会话(IE8下在WINServer03说有BUG,我没有试过),当然Session的唯一标示:SessionID是通常保存在Cookies中的(也可以保存在URL中,cookie禁用的情况下,可以通过配置来确定cookie使用的方式)。

image

也可以在webconfig中配置

<sessionState mode="InProc" cookieName="Asp.Net_SessionKey" cookieless="UseCookies"></sessionState>

ASP.Net中HttpCookie对象的HttpOnly 属性 指定一个Cookie 是否可通过客户端脚本访问。不能通过客户端脚本访问为 true;否则为 false。默认值为 false。此属性并不能完全阻止客户端在本地获取cookies,但是可以增加通过脚本直接获取的难度。
Microsoft Internet Explorer 版本 6 Service Pack 1 和更高版本支持 Cookie 属性 HttpOnly。

JS下操作

在Javascript中Cookie是一个字符串,通过BOM对象下的document.cookies获取,或者使用JQ插件(jquery.cookie.js)来操作

//获得coolie 的值
    function cookie(name){   
       var cookieArray=document.cookie.split("; "); //得到分割的cookie名值对   
       var cookie=new Object();   
       for (var i=0;i<cookieArray.length;i++){   
          var arr=cookieArray[i].split("=");       //将名和值分开   
          if(arr[0]==name)return unescape(arr[1]); //如果是指定的cookie,则返回它的值   
       }
       return "";
    }
      
    function delCookie(name)//删除cookie
    {
       document.cookie = name+"=;expires="+(new Date(0)).toGMTString();
    }
      
    function getCookie(objName){//获取指定名称的cookie的值
        var arrStr = document.cookie.split("; ");
        for(var i = 0;i < arrStr.length;i ++){
            var temp = arrStr[i].split("=");
            if(temp[0] == objName) return unescape(temp[1]);
       }
    }
      
    function addCookie(objName,objValue,objHours){      //添加cookie
        var str = objName + "=" + escape(objValue);
        if(objHours > 0){                               //为时不设定过期时间,浏览器关闭时cookie自动消失
            var date = new Date();
            var ms = objHours*3600*1000;
            date.setTime(date.getTime() + ms);
            str += "; expires=" + date.toGMTString();
       }
       document.cookie = str;
    }
      
    function SetCookie(name,value)//两个参数,一个是cookie的名子,一个是值
    {
        var Days = 30; //此 cookie 将被保存 30 天
        var exp = new Date();    //new Date("December 31, 9998");
        exp.setTime(exp.getTime() + Days*24*60*60*1000);
        document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
    }
    function getCookie(name)//取cookies函数       
    {
        var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
         if(arr != null) return unescape(arr[2]); return null;
      
    }
    function delCookie(name)//删除cookie
    {
        var exp = new Date();
        exp.setTime(exp.getTime() - 1);
        var cval=getCookie(name);
        if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString
    }

票据的安全性

ASP.NET中的Form验证也同样用了cookie来表示用户的身份,ASP.NET中使用Form验证也很简单

    <authentication mode="Forms" >
      <forms name="ASPXAUTHKey" cookieless="UseCookies" timeout="3000"  defaultUrl="/index.html"></forms>
    </authentication>

如上参数timeout设置票据的有效时间也就是cookie的有效时间,具体参数如下

属性名 默认值 描述
name .ASPXAUTH cookie名
timeout 30分钟 超时时间
slidingExpiration true 滑动过去时间
domain None 跨子域共享(www.example.com和a.example.com)
path / 设置验证cookie发送到指定的URL,这个让我们可以在同一个域中寄宿多个应用程序而不会暴露彼此的验证cookie
loginUrl /login.aspx 如果表单需要用户登录,重定向到指定的登录页面
cookieless UserDeviceProfile 启用无cookie验证
requireSSL false 设置为true会建议浏览器仅仅在使用SSL加密的请求中传递cookie

 

 

 

 

 

 可以使用FormsAuthentication.SetAuthCookie("Irving", true);来登录,默认会生成一个加密后的cookie 这里需要说明一个重要的配置文件machineKey 节点 这个文件在.NET安装的目录里,票据安全性的保证来自于cookie数据的机密和使用服务器的machine keys的签名,也可以配置实用哪一种加密方式加密<machineKey decryption="DES" /> ,如果有二级域名,SSO等功能的系统,必须确保生产服务器上具有相同的machine keys,可以使用IIS来配置管理等,而票据的安全性与源于与此。

WCF中的Cookie:http://msdn.microsoft.com/ZH-CN/library/bb398778%28v=vs.100%29.aspx

优缺点

个人觉得一般操作Cookie默认设置HttpOnly,不建议使用JS来操作Cookie,对于 Cookie 的域(Domain)和路径(Path)设置制定策略

Refer:

http://msdn.microsoft.com/ZH-CN/library/ms178194%28v=vs.100%29.aspx

http://en.wikipedia.org/wiki/HTTP_cookie

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

posted @ 2013-03-08 00:15  花儿笑弯了腰  阅读(1558)  评论(0编辑  收藏  举报