我真的不会用cookie

Author : lovecicy

说来惭愧,作为一个拥有三年工作经验的前端,我没用过cookie,尽管在许多面试题集中都会有描述cookie和localStorage的区别的题目。印象中的cookie,是个古老的,丑陋的,不安全的WEB 1.0时代的产物,它早就应该被淘汰,所以我从来没觉得我需要花时间在它上面。但是最近项目要做优化,需要用到cookie,这才开始了我的cookie初探。

项目中要做的优化是,当用户登陆以后,记住用户信息,包括用户名,用户等级等信息。这样,在用户登陆后,其他的页面就不需要每次都发送一个请求获取这些信息。

很简单的需求,但是在实现的过程中,还是发现了一些问题,比如cookie串了,cookie只在某些页面有效等,接下来,我将介绍cookie的参数,和cookie的操作方法以及一些坑。没有什么高深的内容,高手请绕道。

一、cookie的参数

cookie是document对象的一个属性,并且行为和普通的JS对象不同,我给它的行为命名是:零存整取

1. 读取cookie信息

要获取cookie的信息,只有一种方式,通过document.cookie读取所有的cookie,返回的值为所有cookie的键值对,通过分号+空格分隔('; '):

var allCookies = document.cookie;
console.log(allCookies); // 输出格式 'username=test; userlevel=7; userarea=Boston'

零存整取,这里我们做的是整取,所有的cookie都会被取出来,但是只有cookie的键名和cookie的值。

2. 设置cookie

与获取cookie类似的,往cookie里添加cookie也很简单:

document.cookie = newCookie;

上面的newCookie也是一个字符串,格式同上面的输出格式一样为键值对,不过一次只能添加或修改一个cookie。设置cookie时,以下属性可以被添加,使用分号+空格('; ')作为前缀:

  • ; path=path_value ,默认值为当前文档的路径,并且必须为绝对路径,如果未指定,默认为当前文档所处的路径
  • ; domain=domain_value,指定可访问的域(e.g., ‘example.com’, ‘.example.com’ (包括所有的子域名), ‘subdomain.example.com’) 如果未指定,默认为当前域
  • ; expires=date-in-GMTString-format cookie的过期时间,使用GMT时间格式,如果未指定,则在当前session结束后过期
  • ; secure 用于设置是否只能通过安全协议如HTTPS传输

二、cookie操作

虽然cookie很简单,但是浏览器并没有提供我们操作cookie的JS接口。于是,在使用前,我们必须自己写一个小型的库来方便cookie的操作,当然,网上已经遍地都是了,我们没必要自己再去实现一个了。下面是一个比较常用的例子:

function delCookie(name)//删除cookie
{
   document.cookie = name+"=; expires="+(new Date(-1)).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;
}

三个方法,简单易用。

三、那些坑们

在使用的过程中,还是碰上了一些坑的,在这里和大家分享下,也给自己做个笔记。

1. cookie在某些页面不存在

当用户登陆后,来到首页,在首页中,我发送一个请求获取到当前用户的信息。当跳转到其他页面时,会检查cookie是否存在,不存在则重新发送请求获取。结果首次进入某些页面时需要获取一次。

这里的原因是,path没有设置,因此cookie默认在首页的path下,而在不同path下的页面就无法获取到了,解决方法也很简单,给每个cookie加上; path=/,done!

2. cookie串了

cookie串了的表现是:这个页面显示的是当前用户,到其他页面可能会显示其他已经登陆过的用户的信息。

这里的原因,一部分是因为path没有设置,一部分是因为用户登出后,没有清理cookie。当没有设置path时,登出时清除的cookie是当前页面path下的cookie,而没有清除所有页面的cookie。而如果登出时没有清理cookie,而path又没有设置,则后来登陆的用户进入这个页面时,获取到的还是之前用户的cookie,因此串了。

解决方法也很简单,设置path为网站根目录,同上,同时,监听登出事件,清理所有cookie。

3. session过期后,cookie没过期

这个是因为用户长期没有操作,session已经过期,但是cookie还没有过期,因此表现为session过期前登陆的用户的cookie被保留。

解决的办法是,当session过期,后台重定向页面到登陆页面时,在登陆页面中首先做一次cookie的清理即可。

目前碰到的cookie的问题就是这些,关于cookie的安全问题,还有待研究,当然,重要的一点是,cookie不安全,别把重要信息放在cookie里就是了,欢迎有经验的同学赐教。


参考:
[1] Mozilla

standard
  1. luckyGirl - 2014 年 11 月 17 日 9:51 上午

    暂时还没有遇到非用cookie的情境,在微博会有个全局变量$CONFIG对象,用来记录各种常用公用信息

    回复

Have your say