JS 本地数据存储之 cookie

JS 本地数据存储之 cookie

JavaScript 操作 cookie

本来只是想简单看看 cookie、localStorage 和 sessionStorage 的,没想到一搜索扩展了很多知识。中心主题集中在 web storage (localStorage, sessionStorage) 的认识上,以及怎么使用它们。不过,在此之前,先来认识一下小小的 cookie 吧。

其实,除了经常讨论到的 cookie、localStorage 和 sessionStorage 外,还有 IE 独有的 userData,几乎已经淘汰的 Flash(现在有 HTML5 啦),Firefox 独有的 globalStorage(Firefox13 开始不再支持),以及 Google Gears SQLite(需要安装像 Flash 那样的插件)1。这么看来,只有标准化、通用化的技术才能经住考验,得以广泛延续推广使用。

那今天就来好好看看历史悠久的 cookie 吧 ,学以致用!

在没有 web storage 之前,是通过 cookie 在客户端存储会话信息的。它的大小通常限制为 4093 bytes (不同浏览器会有所区别),因此不适合大量数据的存储。这种技术是在 1993 年 Netscape 的 Lou Montulli 为了提高用户的访问速度发明的2

当用户通过 HTTP 协议访问一个服务器时,这个服务器会将一些 key/value 键值返回客户端,并给这些数据加上一些限制条件,符合条件的用户下次访问该服务器时,这些数据又被完整地返回给服务器。所以 cookie 是在客户端和服务器间来回传递的,通过 HTTP 的 Set-Cookie 响应头部设置3。例如:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: page_loaded=25; Expires=Wed, 09 Jun 2021 10:18:14 GMT

这里,浏览器接收到表明回应成功的 HTTP 200 代码,以及回应的内容类型,通过 Set-Cookie 头部创建了一个 cookie:

NameValueExpires
page_loaded25Wed, 09 Jun 2021 10:18:14 GMT

除非在 Wed, 09 Jun 2021 10:18:14 GMT 之前刷新,否则该 cookie 将在这时间之后无效并被客户端移除。如果它没有被移除,将来所有的来自该网站(cookie 在性质上是绑定在特定的域名下的)的请求中都将携带类似的响应头部:

GET /index.html HTTP/1.1
Host: www.example.com
Cookie: page_loaded=25;
  • 简单:cookie 是基于文本的轻量结构,用简单的键值对即可定义

  • 可配置到期规则:cookie 可以在客户端会话结束时到期,也可以在客户端计算机上无限期存储,取决于客户端的到期规则

  • 数据持久性:虽然客户端上的 cookie 保留时间取决于客户端上的到期规则以及用户干预,但 cookie 通常是客户端上持续时间最长的数据保存形式

  • 不需要任何服务器资源:cookie 是存储在客户端上,由客户端发送后再由服务器读取

  • 数量和长度限制:每个域的 cookie 总数是有限的。IE6 或更低版本最多有 20 个 cookie;IE7 和之后的版本最多有 50 个;Firefox 最多有 50 个;Chrome 和 Safari 没作硬性限制4,而单个 cookie 最多 4093 bytes,超出部分会被截掉。具体浏览器的限制可参考 Iain Roberts 的测试5

  • 安全性:潜在隐私和安全影响方面,cookie 一直有个坏名声。他们很容易受到安全问题攻击影响,例如关键攻击载体的 CSRF (Cross Site Request Forgery),XSS (Cross Site Scripting Attacks) 以及 Session Hijacking 。cookie 把所有要保存的数据通过 HTTP 协议的头部在客户端和服务器端来回传递,所有的数据都存储在客户端里,所以这些 cookie 数据可以被轻松访问到,如果 cookie 被人拦截了,那人就可以取得所有的信息。即使加密也与事无补,因为拦截者并不需要知道 cookie 的意义,他只要原样转发 cookie 就可以达到目的了

  • 性能问题:由于每次请求都会携带 cookie 信息,所以在 cookie 中大量存储信息会影响特定域的请求性能

在 JavaScript 中,可以通过 document.cookie 来操作 cookie 对象。例如,可用以下代码遍历 cookie:

if (document.cookie) {
  var cookies = document.cookie.split(";");
  var info = '';
  for (var i = 0; i < cookies.length; i++) {
    var aCookie = cookies[i].split("=");
    info += (aCookie[0] + " = " + aCookie[1] + '\n');
  }
  console.log('cookie info:\n\n' + info);
} else {
  console.log('no cookie exist')
}

另外,cookie 还有一些属性可以设置:

  1. expires 属性:该属性指定了 cookie 的生存期,默认情况下 cookie 是暂时存储的,只在客户端会话期间存在,用户退出后这些值就丢失了。如果想让 cookie 存在一段时间,就要用 expires 属性设置一个未来过期的时间。

  2. path 属性:它指定与 cookie 关联在一起的网页。默认情况下,cookie 会与创建它的网页、该网页处于同一目录下的网页以及与其子目录下的网页关联。

  3. domain 属性:domain 属性可使多个 web 服务器共享 cookie,但不能将一个 cookie 的域设置成服务器所在域之外的域。

  4. secure 属性:它是一个布尔值,指定在网络上如何传输 cookie。默认是不安全的,通过一个普通的 HTTP 连接传输。

例如,可通过以下方法设置一个 cookie:

function setCookie(cname, cvalue, exdays) {
  var d = new Date();
  d.setTime(d.getTime() + (exdays*24*60*60*1000));
  var expires = "expires="+ d.toUTCString();
  document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

更多的例子可参见 w3schools 的 JavaScript Cookies

好了,先说到这里,下次继续 web storage 的话题。

Ads by Google

林宏

Frank Lin

Hey, there! This is Frank Lin (@flinhong), one of the 1.41 billion . This 'inDev. Journal' site holds the exploration of my quirky thoughts and random adventures through life. Hope you enjoy reading and perusing my posts.

YOU MAY ALSO LIKE

Using Liquid in Jekyll - Live with Demos

Web Notes

2016.08.20

Using Liquid in Jekyll - Live with Demos

Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.

Self-host comments in Jekyll, powered by Firebase real-time database

Tutorials

2017.03.25

Self-host comments in Jekyll, powered by Firebase real-time database

It's convenient to set up a comment system in Jekyll site with external social comment systems like Disqus or Duoshuo (多说). However, as you all know, Disqus was blocked in China and Duoshuo is going to shutdown. It's the time to rethink about the comment system (although I didn't get too many comments →_→), simple and controllable. And it becomes true with Firebase database.

TOC

Ads by Google