# 浏览器存储

由于 HTTP 是无状态的协议,不能保存每一次请求的状态,所以需要给客户端增加 Cookie 来保存客户端的状态。Cookie 的作用主要用于 用户识别 和 状态管理 。

HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。

  • Cookie主要用于:

    • 会话状态管理
    • 个性化设置
    • 浏览器行为跟踪
  • Cookie特点:

    • 大小受限,一般为4kB;
    • 同一个域名下存放Cookie个数限制,一般20个;
    • 设置过期时间;
    • 每次发起请求都会携带域名下的Cookie;
    • 支持设置HttpOnly,防止Cookie被客户端访问,前端无法操作cookie
    • 性能的局限性。如果不设置 CookieDomainpath ,是要设置了 Cookie 就会被发送到各个域名下,随着请求数量的变多,性能也会出现很大的问题。
    • 安全的局限性。 Cookie 明文传输,被攻击劫持之后,服务器的资源会被窃取。且如果不设置HttpOnly 攻击者会通过 JS 获取到 Cookie

TIP

  • Cookie以名/值对形式存储,

username =linjiaheng

  • 创建Cookie

document.cookie = "username=linjiaheng"

  • 添加过期时间

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";

  • 使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

  • 读取Cookie: var x = document.cookie
  • 删除Cookie document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT;注意,当您删除时不必指定 cookie 的值。

document.cookie 属性看起来像一个普通的文本字符串,其实它不是。即使您在 document.cookie 中写入一个完整的 cookie 字符串, 当您重新读取该 cookie 信息时,cookie 信息是以名/值对的形式展示的。如果您设置了新的cookie,旧的 cookie 不会被覆盖。 新 cookie 将添加到 document.cookie中。

// 设置cookie值的函数
function setCookie(cname,cvalue,exdays)
{
  var d = new Date();
  d.setTime(d.getTime()+(exdays*24*60*60*1000));
  var expires = "expires="+d.toGMTString();
  document.cookie = cname + "=" + cvalue + "; " + expires;
}

// 获取cookie值的函数
function getCookie(cname)
{
  var name = cname + "=";
  var ca = document.cookie.split(';');
  for(var i=0; i<ca.length; i++) 
  {
    var c = ca[i].trim();
    if (c.indexOf(name)==0) return c.substring(name.length,c.length);
  }
  return "";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

TIP

cookie一般分为两种:

  • session cookie,这种cookie会随着用户关闭浏览器而被清除,不会被标记在任何过期时间Expires或最大时限Max-age
  • permanent cookie。和session cookie相反,会在用户关闭浏览器之后被浏览器持久化存储。

# Cookie安全性

服务器端可以对cookie进行一些关键配置,以保障cookie的使用安全。

  • Secure:仅在HTTPS安全通信时才会发送Cookie
  • HttpOnly:使用Cookie不能被js脚本访问(防止跨站脚本攻击XSSCookie信息的窃取)。没有这样设置,像XSS就可以去获取到cookie
  • SameSite:在跨域情况下,相关cookie无法被请求携带。主要防止跨站伪造CORF的攻击:
    • Strict:浏览器完全禁止第三方请求携带Cookie
    • Lax:只能在get方法提交表单情况或者a标签发送get请求的情况下可以携带Cookie
    • none:默认,请求会自动携带上Cookie

# localStorage

  • 特点:
    • 大小限制为5MB~10MB;
    • 在同源的所有标签页和窗口之间共享数据
    • 数据仅保留在客户端,不和服务器通信;
    • 数据持久存在且不会过期,重启浏览器仍然存在,除非手动清除;
    • 对数据的操作是同步的;

TIP

  1. localStorage.getItem()'null'而不是null,字符串存储null,因为localStorage 只支持 string 类型的存储。
  2. 使用 localStorage.hasOwnProperty() 检查 localStorage 中存储的数据里是否保存某个值hasOwnProperty() 方法检查对象自身属性中是否具有指定的属性,返回一个布尔值。换句话说就是检查 localStorage 中存储的数据里是否保存某个值。sessionStorage也一样。
  3. localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡。
  4. localStorage不能被爬虫抓取到。

# sessionStorage

与服务端的 session 类似,sessionStorage 是一种会话级别的缓存,关闭浏览器时数据会被清除。需要注意的是 sessionStorage 的作用域是窗口级别的,也就是说不同窗口之间保存的 sessionStorage 数据是不能共享的。

  • 特点:
    • 数据只存在当前浏览器的标签页
    • 关闭浏览器标签页后消失
    • localStorage统一的API接口;
    • 对数据操作是同步的

# IndexedDB

  • 特点:
    • 存储空间大,存储空间可以达到几百兆甚至更多;
    • 支持二进制存储:它不仅可以存储字符串,而且还可以存储二进制数据;
    • IndexedDB 有同源限制,每一个数据库只能在自身域名下能访问,不能跨域名访问;
    • 支持事务型:IndexedDB 执行的操作会按照事务来分组的,在一个事务中,要么所有的操作都成功,要么所有的操作都失败;
    • 数据操作是异步的:使用 IndexedDB 执行的操作是异步执行的,以免阻塞应用程序。
  1. 首先打开数据库
let openRequest = indexedDB.open(name, version) // name: 数据库名称;version:一个正整数版本,默认为1
1