1.cookie的诞生

由于HTTP协议是无状态的,服务端的业务必须带用户状态,cookie的诞生最初就是为了存储web中的用户状态以及其他的相关状态,以方便服务器使用。比如是否用户第一次访问网站,用户是否登录等。Cookie目前最新的规范是RFC 6265,它是一个由浏览器和服务器共同协作实现的规范。

2.cookie的工作原理

Cookie的处理基本步骤是:服务器向客户端发送cookie;浏览器保存cookie;浏览器再次访问服务器带上cookie;可以通过有效期来限制cookie的访问时间,并且cookie不能通过跨域来访问,还有一些对象依赖于cookie,比如session。还有就是客户端cookie数量限制在300个,不能超过4kb,每个web站点设置的cookie数量不能超过20个。

2.1 服务器端的发送与解析

服务端向客户端发送cookie是通过http响应报文实现的,在Set-Cookie中设置需要向客户端发送的cookie,格式如下:

Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure" 

其中name=value是必选项,其他都是可选项。Cookie的主要构成如下:

  • name:一个唯一确定的cookie名称。通常cookie的名称不区分大小写。
  • value:存储在cookie中的字符串的值。最好为cookie中的name和value进行url编码。
  • domain:cookie对于那个域是有效的。客户端响应一次之后,所有向这个域发送的请求都会包含这个cookie信息。注意这个值也可以包含子域(例如:如果domain是aliyun.com,则对阿里云所有的子域都有效,比如,访问yq.aliyun.com,xxx.aliyun.com的请求都会带上这个cookie)。
  • path:表示这个cookie影响到的路径,浏览器会根据这个配置向指定的域中匹配的路径发送cookie。
  • expires:失效时间,一个时间戳,表示cookie何时应该被删除,换言之就是何时浏览器停止向服务器发送这个cookie。如果不设置这个时间戳,浏览器会在页面关闭时删除所有的cookie。不过也可以在客户端自己设置这个expires时间戳。这个值是GMT时间格式,如果客户端和服务器时间不一致,使用expires就会存在偏差。
  • max-age:和expires作用相同,用来告诉浏览器此cookie过多久失效(单位是秒),而不是一个固定时间点。正常情况下,max-age的优先级高于expires。
  • HttpOnly:告诉浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但是http请求仍然会携带这个cookie。注意这个值虽然在JavaScript脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这个选项一般在服务端设置。
  • secure:安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,http链接则不会传递该信息。就算设置了secure属性也并不代表其他人不能看到本地保存的cookie信息,所以不要把重要的信息放在cookie中。

使用node.js在服务端设置cookie如下:

var http = require('http');
var fs = require('fs'); http.createServer(function(req, res) {
res.setHeader('status', '200 OK');
res.setHeader('Set-Cookie', 'isVisit=true;domain=.yourdomain.com;path=/;max-age=1000');
res.write('Hello World');
res.end();
}).listen(8888); console.log('running localhost:8888') 

下次请求中携带cookie:

直接设置cookie过于简单粗暴,我们可以包装成一个方法:

var serilize = function(name, val, options) {
if (!name) {
throw new Error("coolie must have name");
}
var enc = encodeURIComponent;
var parts = []; val = (val !== null && val !== undefined) ? val.toString() : "";
options = options || {};
parts.push(enc(name) + "=" + enc(val));
// domain中必须包含两个点号
if (options.domain) {
parts.push("domain=" + options.domain);
}
if (options.path) {
parts.push("path=" + options.path);
}
// 如果不设置expires和max-age浏览器会在页面关闭时清空cookie
if (options.expires) {
parts.push("expires=" + options.expires.toGMTString());
}
if (options.maxAge && typeof options.maxAge === "number") {
parts.push("max-age=" + options.maxAge);
}
if (options.httpOnly) {
parts.push("HTTPOnly");
}
if (options.secure) {
parts.push("secure");
} return parts.join(";");

需要注意的是,如果给cookie设置一个已经过去的cookie,浏览器会立即删除该cookie;此外domain项不许有两个点,因此不能设置为localhost。

2.2 服务端解析cookie

cookie可以设置不同的域和路径,所以对于同一个name,value,在不同路径下是可以重复的,浏览器会按照与当前请求url或页面地址最佳匹配的殊勋来先后排序。

所以当前端传递到服务器端的cookie有多个重复的name,value时,我们只需要找到最匹配的那个,也就是第一个。服务端代码示例如下:

var parse = function(cstr) {
if (!cstr) {
return null;
} var dec = decodeURIComponent;
var cookies = {};
var parts = cstr.split(/\s*;\s*/g);
parts.forEach(function(p){
var pos = p.indexOf('=');
// name 与value存入cookie之前,必须经过编码
var name = pos > -1 ? dec(p.substr(0, pos)) : p;
var val = pos > -1 ? dec(p.substr(pos + 1)) : null;
//只需要拿到最匹配的那个
if (!cookies.hasOwnProperty(name)) {
cookies[name] = val;
}/* else if (!cookies[name] instanceof Array) {
cookies[name] = [cookies[name]].push(val);
} else {
cookies[name].push(val);
}*/
}); return cookies;

2.3 客户端的存取

浏览器管理服务器传递过来的cookie,并允许开发者在JavaScript中使用document.cookie来存取cookie。但是这个接口使用起来不方便,它会因为使用它的方式不同而表现出不同的欣慰。

  • 当用来回去属性值时,document.cookie返回当前页面可用cookie(根据cookie的域,路径,失效时间和安全设置)的字符串,字符串格式如下:

    "name1=value1;name2=value2;name3=value3"; 
  • 当用来设置值的时候,document.cookie属性可写,可以设置为一个新的cookie字符串。这个字符串会被解释并添加到现有的cookie集合中。如下:
    document.cookie = "_fa=aaaffffasdsf;domain=.dojotoolkit.org;path=/"

设置document.cookie并不会覆盖cookie,除非设置的name,value,domain,path都和一个已经存在的cookie重复。

由于cookie的读写很不方便,我们可以自己封装一些函数来处理cookie,主要针对cookie的添加,修改,删除操作。

var cookieUtils = {
get: function(name){
var cookieName=encodeURIComponent(name) + "=";
//只取得最匹配的name,value
var cookieStart = document.cookie.indexOf(cookieName);
var cookieValue = null; if (cookieStart > -1) {
// 从cookieStart算起
var cookieEnd = document.cookie.indexOf(';', cookieStart);
//从=后面开始
if (cookieEnd > -1) {
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
} else {
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, document.cookie.length));
}
} return cookieValue;
}, set: function(name, val, options) {
if (!name) {
throw new Error("coolie must have name");
}
var enc = encodeURIComponent;
var parts = []; val = (val !== null && val !== undefined) ? val.toString() : "";
options = options || {};
parts.push(enc(name) + "=" + enc(val));
// domain中必须包含两个点号
if (options.domain) {
parts.push("domain=" + options.domain);
}
if (options.path) {
parts.push("path=" + options.path);
}
// 如果不设置expires和max-age浏览器会在页面关闭时清空cookie
if (options.expires) {
parts.push("expires=" + options.expires.toGMTString());
}
if (options.maxAge && typeof options.maxAge === "number") {
parts.push("max-age=" + options.maxAge);
}
if (options.httpOnly) {
parts.push("HTTPOnly");
}
if (options.secure) {
parts.push("secure");
} document.cookie = parts.join(";");
},
delete: function(name, options) {
options.expires = new Date(0);// 设置为过去日期
this.set(name, null, options);
}
}

当然也有一些第三方的js库,例如:js-cookie

3.HttpOnly

HttpOnly是包含在Set-Cookie Http响应头文件中的附加标志。生成cookie时使用HttpOnly标志有助于降低客户端脚本被访问,修改的风险。

如果一个cookie的选项被设置成HttpOnly = true的话,此cookie只能通过服务器修改,js操作不来。如下:

关于cookie的深入了解的更多相关文章

  1. 超大 Cookie 拒绝服务攻击

    有没有想过,如果网站的 Cookie 特别多特别大,会发生什么情况? 不多说,马上来试验一下: for (i = 0; i < 20; i++) document.cookie = i + '= ...

  2. IE10、IE11 User-Agent 导致的 ASP.Net 网站无法写入Cookie 问题

    你是否遇到过当使用一个涉及到Cookie操作的网站或者管理系统时,IE 6.7.8.9下都跑的好好的,唯独到了IE10.11这些高版本浏览器就不行了?好吧,这个问题码农连续2天内遇到了2次.那么,我们 ...

  3. 解决cookie跨域访问

    一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入c ...

  4. jquery插件的用法之cookie 插件

    一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...

  5. 一个诡异的COOKIE问题

    今天下午,发现本地的测试环境突然跑不动了,thinkphp直接跑到异常页面,按照正常的排错思路,直接看thinkphp的log 有一条 [ error ] [2]setcookie() expects ...

  6. [转载]Cookie/Session的机制与安全

    Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...

  7. jquery.cookie的使用

    今天想到了要为自己的影像日记增加赞的功能,并且需要用到cookie. 记得原生的js操作cookie也不是很麻烦的,但似乎jquery更简单,不过相比原生js,需要额外引入2个文件,似乎又不是很好,但 ...

  8. 跨域问题,前端主动向后台发送cookie

    跨域是什么? 从一个域名的网页访问另一个域名的资源,就会出现跨域.只要协议.端口.域名有一个不同就会出现跨域 例如: 1.协议不同  http://www.baidu.com:80 和 https:/ ...

  9. 【流量劫持】沉默中的狂怒 —— Cookie 大喷发

    精简版:http://www.cnblogs.com/index-html/p/mitm-cookie-crack.html 前言 上一篇文章 讲解了如何借助前端技术,打造一个比 SSLStrip 更 ...

  10. 好好了解一下Cookie

    Cookie的诞生 由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的.Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用.比如判断用户是否是第一次访问网站.目前最新 ...

随机推荐

  1. 阿里云架构师梁旭:MES on 云盒,助力客户快速构建数字工厂

    简介: 四大优势:一站式交付.业务低延时.数据本地驻留.多工厂统一运维 2022年5月18日,在"云上数字工厂与中小企业数字化转型创新论坛"暨"鼎捷MES & 阿 ...

  2. 阿里云张振尧:阿里云边缘云驱动5G时代行业新价值

    ​简介:近日,以"5G融合通信趋势下的技术创新"为主题的2021中国增值电信及虚拟运营高峰论坛在北京召开,阿里云边缘云高级产品专家张振尧发表了<阿里云边缘云驱动5G时代行业新 ...

  3. 理解FPGA内部的同步信号、异步信号和亚稳态

    FPGA(Field-Programmable Gate Array),即现场可编程门阵列.主要是利用内部的可编程逻辑实现设计者想要的功能.FPGA属于数字逻辑芯片,其中也有可能会集成一部分模拟电路的 ...

  4. vue下获得经纬度省市区

    1.根目录html文件引入 <!--引入百度 API,"ak=" 后面一串码是密钥,最好自己申请--> <script type="text/javas ...

  5. 学会使用 NumPy:基础、随机、ufunc 和练习测试

    NumPy NumPy 是一个用于处理数组的 Python 库.它代表"Numerical Python". 基本 随机 ufunc 通过测验测试学习 检验您对 NumPy 的掌握 ...

  6. SQL Server实战五:存储过程与触发器

      本文介绍基于Microsoft SQL Server软件,实现数据库存储过程与触发器的创建.执行.修改与删除等操作. 目录 1 交互式创建并执行--存储过程一 2 交互式创建并执行--存储过程二 ...

  7. Linux中的touch命令

    Linux中一个文件有3种时间属性,分别是mtime,ctime,atime: modification time (mtime) 当该文件的『内容数据』变更时,就会升级这个时间!内容数据指的是文件的 ...

  8. VForm

    VForm是一款基于Vue 2/Vue 3的低代码表单,支持Element UI.iView两种UI库,定位为前端开发人员提供快速搭建表单.实现表单交互和数据收集的功能. VForm全称为Varian ...

  9. 抽丝剥茧:详述一次DevServer Proxy配置无效问题的细致排查过程

    事情的起因是这样的,在一个已上线的项目中,其中一个包含登录和获取菜单的接口因响应时间较长,后端让我尝试未经服务转发的另一域名下的新接口,旧接口允许跨域请求,但新接口不允许本地访问(只允许发布测试/生产 ...

  10. 详解 XSS 攻击原理

    更多优质博文请关注:听到微笑的博客 跨站脚本攻击(Cross Site Scripting)本来的缩写为CSS,为了与层叠样式表(Cascading Style Sheets,CSS)的缩写进行区分, ...