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…
发表回复