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…