首页 > Web传统技术, 代码库, 技术随笔 > Javascript操纵Cookie

Javascript操纵Cookie

Web传统技术, 代码库, 技术随笔

在讲如何使用Javascript操纵Cookie时,我们先来了解一下Cookie的基本常识。

Cookie,又称Http Cookie,是存储在客户端本地的一小段信息。我们可以简单地把Cookie理解为客户端浏览器上的一个小硬盘,我们会在上面存取一些信息,通常用作Http状态的维护,现在也经常被用作跟踪用户行为的一种常见方式。

Cookie的属性

每一个Cookie都有如下几个属性:

  • 名称   
  • 主机域
  • 路径
  • 安全级别
  • 过期时间

其中“名称”、“主机域”,“路径”三者一起唯一标识了一个Cookie。
大多数Cookie在设置的时候都只是显式的设置了Cookie的名称和值,这种情况下,浏览器会自动的使用location.host来设置Cookie的主机域,将路径设置到根目录“/”下。例如,当你在www.example.com上面使用document.cookie="name=value"设置了一个Cookie,那么这个Cookie就拥有了如下属性:

  • 名称 —— name
  • 值 —— value
  • 主机域 —— www.example.com
  • 路径 —— /
  • 安全级别 —— No
  • 过期时间 —— 浏览器会话结束(关闭浏览器)

第一方和第三方Cookie的区别

第一方Cookie指的是设置在当前网站域上面的Cookie,而第三方Cookie指的是设置在其他域上的Cookie。

第一方Cookie比较好理解,我们通常遇到的都是属于第一方Cookie。在客户端Javascript中,我们只能操纵第一方Cookie,也就是说,我们不能在www.example.com主机上,设置www.google.cn的Cookie,这样就乱套了。

第三方Cookie不容易让人注意到。假设我们在公司网站www.example.com上面使用了map.google.com的地图服务,而Google地图在使用时又希望在用户这边设置一些Cookie,就跟用户直接访问自家网站(map.google.com)一样,如Session信息等,那么它会在返回的HTTP Response中包含set-cookie的报头,但由于是第三方域,存在安全问题,所以必须还在响应中包含一个P3P的主机头(P3P头中存的是隐私策略的摘要)来实现Cookie的第三方存取(注意,此时Cookie还是设置在b.com上面的)。IE中可以设置对第三方Cookie存取的限制。

Javascript操纵Cookie

在客户端使用Javascript操纵Cookie存在很多的不便之处,例如在读取Cookie的时候,只能通过手动解析document.cookie字符串得到指定cookie的值,不能得到其他任何信息,如设置的主机,路径以及过期时间等。

/**
 * 查询指定名称的Cookie值
 * @note 需要注意有可能出现同名cookie的问题
 * @param {Object} key
 * @param {Object} 设置当读取不到key时返回的默认值
 * @return {String} 返回读取到的Cookie的值,
 * 如果读取不到相应的Cookie,则判断defValue是否有效,有效则返回defValue,否则返回null
 */
function getCookie(key,defValue){
    var cookie,value;
    if(!key){
        return null;
    }
    
    cookie = document.cookie;
    // 所有cookie的key都小写化处理
    key = key.toLowerCase();
    
    value = find(cookie,key+"=",";",null,false,null);
    return value === null ? defValue : unescape(value);
}
/**
 * 设置cookie
 * @param {String} key
 * @param {String} value
 * @param {Number} expires 单位为秒
 * @param {String} path 路径
 * @param {String} domain 主机
 * @param {Boolean} secure 安全级别
 */
function setCookie(key, value, expires, path,domain,secure){
    // key无效则不做任何操作
    if(!key){
        return;
    }
    
    // 所有cookie的key都小写化处理
    key = key.toLowerCase();
    
    key = key + '=' + escape(value) + ";";
    expires = expires ? ("expires=" + new Date(new Date().getTime() + expires * 1000).toGMTString()) + ";" : "";
    path = !!path ? "path=" + path + ";" : "path=/;";
    domain = domain ? ("domain=" + domain) + ";" : "";
    secure = secure ? "secure=true;" : "";
    document.cookie =[key,expires,path,domain,secure].join("");
}
/**
 * 删除指定Cookie
 * @param {Object} key
 * @param {Object} path
 * @param {Object} domain
 */
function delCookie(key,path,domain){
    // 超时设置为过去的时间,cookie会立即失效
    key = key.toLowerCase();
    setCookie(key,"",-1000,path,domain);    
}
/**
 * 从字符串中获取夹在指定前缀和后缀之间的值
 * @example
 * userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.0.2) Gecko/2008082714 Firefox/3.0.2"
 * 
 * prefix="windows nt"
 * suffix=";"
 * find(userAgent,prefix,suffix) returns " 5.2";
 * @param {Object} str 源字符串
 * @param {Object} prefix 前缀
 * @param {Object} suffix 结束符,若不指定,则匹配到字符串结尾;如果指定了,但是匹配不到,则同样匹配到字符串结尾。
 * @param {Boolean} matchFirstOnly 是否找到第一个匹配项,设置为false则查找最后一个匹配项,默认为false
 * @param {Boolean} ignoreCase     忽略大小写来查找,默认值为true
 * @param {Boolean} trimBlank 是否删除值首尾的空白符,默认值为true
 * @return {String} 查找到的字符串,若找不到则返回null
 */
function find(str,prefix,suffix,matchFirstOnly,ignoreCase,trimBlank){
    var start,end,middle,value=null;
    matchFirstOnly = (matchFirstOnly === true);
    ignoreCase = (ignoreCase !== false);
    trimBlank = (trimBlank !== false);
    // 如果忽略默认值
    if(ignoreCase){
        str = str.toLowerCase();
        prefix = prefix.toLowerCase();
        suffix = suffix && suffix.toLowerCase();
    }
    
    if(matchFirstOnly){
        start = str.indexOf(prefix);
    }else{
        start = str.lastIndexOf(prefix);
    }        
    if (start > -1) {
        // 如果没有指定后缀,则直接匹配到字符串结尾
        middle = start + prefix.length;
        if (!suffix) {
            value = str.substring(middle);
        }
        else {
            end = str.indexOf(suffix, middle);
            if (end > -1) {
                value = str.substring(middle, end);
            }
            else {
                value = str.substring(middle);
            }
        }
        if(trimBlank){
            value = value.replace(/^\s*(.*?)\s*$/, '$1');
        }    
    }
    
    return value;
}

本博客遵循CC协议2.5,即署名-非商业性使用-相同方式共享
写作很辛苦,转载请注明作者以及原文链接~
如果你喜欢我的文章,你可以订阅我的博客:-D点击订阅我的文章

  1. X﹏X 到现在还没有评论~
  1. 暂时没有trackbacks.