乐趣区

存储sessioncookiestorage

1. session:

  • 概念:

    • 是一个数据对象,用来存储信息。
    • 是一个抽象对象,指代多个有关联的 http 请求所构成的一个会话。多次请求之间能够共享一些信息。
  • 实现:

    • 在每个请求的参数或者数据中带上相关的信息。不受 cookie 限制,但是受到 请求长度的限制。
    • 用 cookie 存储,可以是整个 session 的具体数据,也可以是 session 的标识(sessin_id).
  • 特点:

    • 只存在与 服务端。
    • 并不是 服务器 原生支持的。是中间件自己创建并管理的。
    • session 仅仅是一个对象信息,可以存到 cookie,也可以存到任何地方(如内存,数据库)。
    • 存到哪,可以开发者自己决定,只要实现一个 store 对象,提供 set,get 方法即可。
    • session_id,是唯一的标识 session 的,以及其他一些必要信息会放在 cookie 中,一起返回到前端。
    • 其他信息,可以保存在 session_id 命名的文件中。
  • session 的负面影响:

    • 性能影响。如果用户很多,信息都保存在 sessin 文件中,查找耗时太多(可以分目录和哈希等)。可以自己实现 session,将 session 信息存放到数 据库当中,这样做最好对数据库进行一下缓存的设置了,不然对上千万的数据进行太频繁的检索,也是蛮耗资源的。
  • session 的清除:

    • 定期清理 session(清除服务端的 session 文件,和 客户端的 cookie 信息)
    • cookie,expires 设置为 负值,客户端的 cookie 信息就会过期,浏览器就会自动删除。
  • koa-session 的 原理:【有空一定要看看源码,看源码要注意命名、特色、知识点的学习。也会学习 koa 插件的写法的过程】【看源码,要先有整体把控图,然后逐步去分析啊】

    • 使用流程:

      • app.use(session(CONFIG, app)); // 初始化 koa-session 中间件
      • let n = ctx.session.views || 0; // 每次都可以取到当前用户的 session
    • 初始化的时候,把 session 对象挂载在 app.context 上。所以后面可以 从 ctx.session 上获得 session
    • 在接到 http 请求的时候,
    • 默认把数据 json,塞进了 cookie,即 cookie 来存储加密后的 session 信息。
    • 如果设置了外部 store,会调用 store.set() 去保存 session。具体的保存逻辑,保存到哪里,由 store 对象自己决定!
    • 用 cookie 存储的时候,对 session(包含过期时间)序列化后做一个简单的 base64 编码。
    • 就算信息保存在文件中,还是必不可少的需要 cookie
    • session_id 的默认实现是 一个时间戳加随机字符串。
    • koa-session 允许用户在 config 中配置自己的编码和解码函数,因此完全可以使用自定义的加密解密函数对 session 进行编解码
  • session 的鉴权过程:

    • 用户登录的时候,服务端生成一个会话和一个 id 标识
    • 会话 id 在客户端和服务端之间通过 cookie 进行传输
    • 服务端通过会话 id 可以获取到会话相关的信息,然后对客户端的请求进行响应;如果找不到有效的会话,那么认为用户是未登陆状态
    • 会话会有过期时间,也可以通过一些操作(比如登出)来主动删除
  • token 的典型流程:

    • 用户登录的时候,服务端生成一个 token 返回给客户端
    • 客户端后续的请求都带上这个 token
    • 服务端解析 token 获取用户信息,并响应用户的请求
    • token 会有过期时间,客户端登出的时候也会废弃 token,但是服务端不需要任何操作
  • session 和 token 的区别:

    • session,要求服务端存储信息,并根据 id 能够检索,而 token 不需要。
    • 服务端 要 通过 token 来解析 用户身份,也需要定义好相应的协议。
    • session 一般使用 cookie 来交互。token,可以是 cookie,也可以是 其他 heaser,甚至可以放在请求的内容中。不使用 cookie 可以带来跨域的便利性
    • 很多情况下,sessin 和 token 可以一起使用。
  • token 是如何生成的呢?

    • 一般由第三方服务来提供。
  • 参考:

    • https://www.cnblogs.com/woodk…

      • 看源码的时候,可以画一下 主要模块的脑图,更有助于理解。
    • https://www.cnblogs.com/longh…
    • https://www.jianshu.com/p/8f4…
    • https://segmentfault.com/a/11…

2. cookie

  • 存储大小:每条的存储空间为 4k;
  • 特点:

    • cookie 没有显示的删除函数,可以设置 expire 过期事件,自动触发浏览器的删除机制。
    • 服务器通过设置响应头来设置客户端的 cookie,Set-Cookie: cookie- 名 =cookie 值。可以同时添加多个 Set-Cookie,从而设置多个 cookie 的值。
    • 不允许存储敏感信息(用户名,密码等),一定要存储,要设置 cookie 为 httponly,另外考虑使用 非对称加密
    • cookie 通常与 session 一起使用。

      • 登录时,server 端存储 用户信息相关的 session。
      • server 端,生成的 sessionid 会放在 cookie 中,对应域名下就有了这个 cookie。
      • 以后会自动带这个 cookie,server 根据 id 找到 session,获取用户信息。
  • 设置 cookie:

        document.cookie="userId=828";
        document.cookie="userName=hulk"; 
        此时浏览器将会维护两个 cookie,分别为 userId 和 userName;相当于:document.addCookie("userId=828");
        document.addCookie("userName=hulk");
        如果要改变一个 cookie 的值,只需重新赋值,例如:document.cookie="userId=929";
  • 获取 cookie:

    var strCookie=document.cookie;
    console.log(strCookie); //userId=828; userName=hulk
    • 只能一次获取所有的 cookie 的值,而不能指定 cookie 名称来获得指定的值。
    • 如果在某个页面创建了一个 cookie,那么该页面所在目录中的其他页面也可以访问该 cookie。
    • 为了控制 cookie 可以访问的目录,需要使用 path 参数设置 cookie。document.cookie=”userId=320; path=/shop”; 就表示当前 cookie 仅能在 shop 目录下使用。
  • 常用的 cookie 操作及其函数实现:

    • addCookie(name, value, expireHours):
        function addCookie(name,value,expireHours){var exdate = new Date();    
            exdate.setTime(exdate.getTime() + expireHours * 60 * 60 * 1000);    
              document.cookie = name + "=" + escape(value) + ((expireHours == null) ? "":";expires=" + exdate.toUTCString());
        }
        toUTCString() 方法可根据世界时 (UTC) 把 Date 对象转换为字符串,并返回结果。
    • getCookie(name):
        function getCookie(name){let arr, reg = new RegExp(`^| ${name} = [^;]*;|$`);
            if (arr = document.cookie.match(reg)) return arr[2];
            else return null;
        }
  • cookie 的可选项:

    • expires/max-age: 设置过期时间。expires 是绝对时间,max-age 是相对时间。如果没有设置过期时间,则表示是一个会话期 cookie,在关闭浏览器后,会被移除。浏览器支持会话恢复,保留 cookie。
    • domain 和 path:path,设置必须匹配的路径或者子路由才会发送 cookie。domain 标识指定了哪些主机可以接受 cookie。如果没有设置,则是当前主机(不包含子域名),否则为设置的域名(包含子域名)。
    • secure 和 httponly:secure 标志 cookie 只能通过 https 传输,可以防止 xss 攻击。httponly 表示 cookie 无法通过 javascript 调用,防止中间人劫持。把 cookie 设置为 secure,只保证 cookie 与服务器之间的数据传输过程加密,而保存在本地的 cookie 文件并不加密。如果想让本地 cookie 也加密,得自己加密数据。
    • samesite:可以设置 SameSite:SameSite=Strict SameSite=Lax。则 cookie 不跨域发送。ajax 中设置 xhr.withCredentials = true;
  • 问题:

    • 问题:“www.qq.com”与“sports.qq.com”公用一个关联的域名”qq.com”,我们如果想让”sports.qq.com”下的 cookie 被“www.qq.com”访问:
    • 解答:我们就需要用到 cookie 的 domain 属性,并且需要把 path 属性设置为“/“。例:document.cookie =“username=Darren;path=/;domain=qq.com“
    • 问题:同域名的资源请求时,会默认带上本地的 cookie,如何优化?
    • 解答:将静态资源分组,分别放在不同的子域下(子域名请求时,是不会带上父级域名的 cookie 的)

3. session 和 cookie 对比:

4. localStorage:

  • 存储大小:一般浏览器支持的是 5M 大小,不同浏览器会有所不同。
  • 是 H5 的新特性,兼容性不是很好。
  • 目前所有的浏览器都会把 localStorage 的值类型限定为 string 类型,这个在对我们日常比较常见的 JSON 对象类型需要一些转换。
  • localStorage 在浏览器的隐私模式下是不可读取的。
  • localStorage 本质上是对字符串的读取,如果存储内容多,会消耗内存空间,会导致页面变卡。
  • localStorage 不会被爬虫抓取到。
  • localStorage 只支持 string 类型的存储。一般我们会将 JSON 存入 localStorage 中,但是在 localStorage 会自动将 localStorage 转换成为字符串形式。这个时候我们可以使用 JSON.stringify() 这个方法,来将 JSON 转换成为 JSON 字符串。读取之后要将 JSON 字符串转换成为 JSON 对象,使用 JSON.parse() 方法:

    let storage = window.localStorage;
    let data = {
          name: 'aaa',
          sex: 'man',
          hobby: 'program'
    };
    let dataString = JSON.stringify(data);
    storage.setItem('data', dataString);
    let json = storage.getItem('data');
    let jsonObj = JSON.parse(json);
    console.log('json', json);
    console.log('jsonObj', jsonObj);
    console.log('dddd', typeof jsonObj);
  • 方法和属性:

    • 添加键值对:setItem(key, value);
    • 获取键值对:getItem(key);
    • 删除键值对:removeItem(key);
    • 清除所有键值对:clear();
    • 获取键名称:key(index);
    • (属性)获取 localStorage 中保存的键值对的数量:length。
    • 获取键值对:
    for (let i = 0; i < localStorage.length; i++) {let key = localStorage.key(i);
        let value = localStorage.getItem(key);
    }
  • 事件:

    • storage 事件:浏览器在 localStorage 数据变化(真正的发生变化)之后给你的一个通知。
    • 包含的属性:

      • storageArea: 表示存储类型(session 或 local)
      • key:发生改变项的 key
      • oldValue:key 的原值
      • newValue: key 的新值
      • url: key 改变发生的 URL(有些早期版本中使用的是 uri 属性)
    • 这个事件兼容性好像不好,要少用。
    • localStorage 存储的数据是不能跨浏览器共用的,一个浏览器只能读取各自浏览器的数据,储存空间 5M.
  • 如何实现两个标签页的数据交互:

    • 调用 localStorage:

      • 在一个标签页里面使用 localStorage.setItem(key,value) 添加(修改、删除)内容;在另一个标签页里面监听 storage 事件。即可得到 localstorge 存储的值,实现不同标签页之间的通信。
      • 将要传递的信息存储在 cookie 中,每隔一定时间读取 cookie 信息,即可随时获取要传递的信息。

5. localStorage 和 cookie 对比:

6. localStorage 和 sessionStorage 的区别:

  • localStorage 属于永久性存储,而 sessionStorage 属于当前会话结束的时候,sessionStorage 中的键值对会被清空。

7. 参考:

  • https://www.jianshu.com/p/e4e…
  • https://www.jianshu.com/p/e3d…
  • https://segmentfault.com/a/11…
  • https://segmentfault.com/a/11…
  • https://www.jianshu.com/p/707…
退出移动版