zoukankan      html  css  js  c++  java
  • 关于Cookies与Session系列一

    这两个东西,最近项目操作的比较少,不过这两个在Web项目开发中一直都扮演着很重要的角色,有时有些细节会不小心就遗忘掉。

    Cookies  的概述

    Cookies是由服务器端生成,发送给客户端,用来保存一些数据文本文件。在用户进行网页浏览时,这家伙会在客户端与服务器之前传递,常用作身份的验证、用户会话识别或存储小型数据。由于cookies是保存在客户端,那么就意味着用户可以修改和读取,因此有人利用木马、病毒窃取用户Cookies并获得用户信息,所以,作为开发人员,Cookies不适合保存重要或者涉及隐私的内容,除非你加密。(当然,作为用户,定期清理这些垃圾是一个好习惯~)

     

    Cookies 的限制

    大多数浏览器支持最大为4096个字节的Cookie,所以Cookie不适合保存大数据。 浏览器也会限制同一个站点下的Cookies数量,一般为20个,超出这个数量的话,旧的Cookie将会被丢弃。 用户可以禁用Cookie,如果禁用后会影响Session的信息保存(相关问题在后续会讲到)

    Cookies  的操作

    由System.Web.HttpCookie中可以看到.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 值。
            //
            // 返回结果:
            //     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; }
    System.Web.HttpCookie(System.Web.dll, v4.0.0.0)

    简单的操作如下

    public ActionResult Index()
            {  
                var cookie = new HttpCookie("MyCookieName", "string value");
                //简单的Cookie
                Response.Cookies.Add(cookie); 
    
                var testCookies = new HttpCookie("MyCookiesInfo");
                //默认属性
                testCookies.Value = "丰富的Cookies";
                //TestCookies.Domain = "testlocalhost";默认为当前网站跟域,如localhost,但如果你想设置域为testlocalhost,嘻嘻,自己试试
                testCookies.Name = "123456"; //这里重置了该Cookies的名称,改为123456
                //额外的属性
                testCookies["TestAttr1"] = "再来个属性";
                testCookies["TestAttr2"] = "再来个属性2";
                //设置超时时间
                testCookies.Expires = DateTime.Now.AddHours(1);
                Response.Cookies.Add(testCookies);
                return View();
            }
    
            public ActionResult About()
            {
                string test = Request.Cookies["MyCookieName"].Value;
                string test2 = Request.Cookies["123456"].Value;
                string test3 = Request.Cookies["123456"]["TestAttr1"];
                Response.Write(test + "|" + test2 + "|" + test3 + "|" + Request.Cookies["123456"].Expires.ToString());
                return View();
            }
     
    About页面输出的结果是 string value|丰富的Cookies&TestAttr1=再来个属性&TestAttr2=再来个属性2|再来个属性|0001/1/1 0:00:00 ­­

    这里可以看到一个cookie操作的特性
    当浏览器向服务器发送 Cookie 信息时,并不包括有效期信息。(Cookie 的 Expires 属性始终返回值为 0 的日期时间值。)
    即服务器不能获取cookie的有效时间来判断cookie是否已经过期。
    那我们能不能改变cookie的有效时间让它提前过期呢?我们修改About的代码如下
               string test = Request.Cookies["MyCookieName"].Value;

                Request.Cookies["MyCookieName"].Value = "我要修改属性啦!";
                Response.Cookies["MyCookieName"].Expires = DateTime.Now.AddDays(-1);


                string test2 = Request.Cookies["123456"].Value;
                string test3 = Request.Cookies["123456"]["TestAttr1"];
              
                Request.Cookies["123456"].Value = "我要修改属性啦!";

    在执行Index时,cookie信息如下

    到About页面时

    只剩下123456这个cookie了,因为我们设置MyCookieName的超时时间比当前时间小,因此客户端自动将这个cookie删除了。

    但请注意,123456的cookie值没有改变!!为什么??别急,我们先来看看我们在操作上述代码时,客户端与服务端是怎么沟通的?对,Http协议。

    Http协议的详细内容就不在这啰嗦了,请去找度娘(屌丝程序员的最爱)。研究协议的最好方法还是抓包,抓包工具很多,以后应该会针对http协议有一篇总结,到时再详细说吧。

    以下是请求Index时的一个抓包的部分截图

    我们可以看到,服务端在HTTP的响应头中通过Set-Cookie】的响应头来进行Cookie的设置
    那么我们在访问About时,抓包截图如下


    可以看到产生了一个Set-Cookie】的响应头,将MyCookieName的Expires时间改变了(比较123456的Expires即可知MyCookieNameExpires变得比当前时间小,故删除操作是客户端自己完成的),因此,客户端就只剩下123456这个cookie了,那为什么123456的值没有改变呢?怎么改变呢?我们再来修改About的代码,增加如下代码
              var temp = new HttpCookie("123456");
                temp = Request.Cookies["123456"];
                temp["TestAttr1"] = "真的要改变属性值啦!";
                Response.Cookies.Add(temp);
    
    

    然后重新由Index页面跳转到About页面

    抓包截图为

    没错,这样才会产生一个Set-Cookie】的响应头
    因此操作cookie的另外一个特性为
    服务端不能直接改变客户端的cookie值,包括超时时间也不能直接修改,需要重新建立一个对应名称的Cookie,然后重新对该Cookie下的的属性赋值,再添加到httpContext中,
    超时时间也一样,只能重写
    虽然修改不了Cookie,但可以取得,那服务端是如何拿到客户端的Cookie信息呢?
    细心的朋友发现了刚才抓包截图中左侧为客户端请求头,很明显客户端(浏览器)在每次请求时会把cookie信息装进请求头中,这里还需要注意一点,我们保存在浏览器上的cookie非常多,难道每次请求都会把所有的cookie放到请求头去么?答案是否定的。
    浏览器会检查当前要请求的域名以及目录, 只要这二项目与Cookie对应的Domain和Path匹配,才会发送。对于Domain则是按照尾部匹配的原则进行的。
     
    最后补充一下和Cookie相关的一些操作
    校验浏览器是否支持Cookies,不支持时可以提示用户
        if (Request.Browser.Cookies)
            {
                //浏览器支持cookies,继续coding......
            }
            else
            {
                //浏览器不支持cookies,那么弹出提示信息或者重定向到新页面进行处理
            }    

    Js也能操作Cookies的,简单的例子如下

    <script type="text/javascript">
        function WriteCookie() {
            var cookie = "cookie_js=22222222; path=/";
            document.cookie = cookie;
        }    
       function ReadCookie() {
            alert(document.cookie);
        }   
    </script>

    读取的效果为

    如果想对读取结果进行解析,请自行处理一下。

    写的效果为



    在前面的代码中,如果你设置 TestCookies.Domain = "testlocalhost" 该cookie将不会被创建,大家能说说是什么原因么?

    
    

     

  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/endysaiwang/p/3719814.html
Copyright © 2011-2022 走看看