一、为什么要用到会话技术?
HTTP请求是无状态的。在互联网发展之始,Web基本上就是文档浏览,服务器不需要记录谁在某短时间浏览了什么内容。而经过互联网的发展,交互式的Web应用兴起,无状态的请求模式已经不能满足需求了,于是用到了会话技术。
二、cookie简介
1、cookie是一种存储在用户本地终端(通常是指浏览器)上的数据。
2、文件大小不超过4kb
3、数据以key-value形式存在
4、可以设置过期时间(生存周期)expires。cookie有两种存储类型cookie:会话型和持久型。expires属性缺省时,为会话型Cookie,仅保存在客户端内存中,并在用户关闭浏览器时失效;持久性Cookie会保存在用户的硬盘中,直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效
5、 cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。
6、当浏览器不禁用cookie时,客户端访问服务器时会自动携带cookie。cookie遵循同源策略(域名、端口一致)
三、session简介
1、session是服务器端存储(存储在内存中)的一个对象,主要用于存储访问过服务器的客户端用户信息。当服务器重启,内存会销毁,存储的用户信息会消失。
2、工作原理:客户端用户使用账号、密码登录服务器,如果登录成功服务器端会生成并存储一个sessionId(字符串)用来标记用户,同时会将sessionId通过cookie返回到客户端,客户端将sessionId存储在cookie中。客户端再次访问服务器时会默认携带cookie中的sessionId(相当于通行证/令牌)
3、由②可知session基于cookie。session这种会话存储方式方式只适用于客户端代码和服务端代码运行在同一台服务器上(前后端项目协议、域名、端口号都一致,即在一个项目下)
4、 session持久化。用于解决重启服务器后session就消失的问题。在数据库中存储session,而不是存储在内存中。通过包:express-mysql-session
四、token简介
1、token是在服务器端生成一串字符串,它存储在客户端而服务器端不存储token但会存储秘钥。秘钥通常共有且唯一。
2、标准的token(JWT)由三部分组成:header(头)、payload(负载)、signature(签名)。其中header中记录了使用的签名算法,payload中记录的是用户信息(根据需要可设置任何信息),signature部分是根据算法+秘钥+信息计算得到的签名。
header.payload.signature
3、token 中的数据是明文保存的(只会用base64编码),还是可以被别人看到的,所以不能在其中保存像密码这样的敏感信息。
4、工作流程:
①客户端用户通过账号密码登录服务器。
②登录成功后服务器端生成token,并通过响应主体发送到客户端。客户端将其保存在cookie(sessionStorage、localStorage也都可以进行存储)中,服务器端不存储token值。
③客户端下次请求时会在headers中添加token字符串。
④服务器端获取headers中的token,解析出header和用户信息。然后对二者重新编码并使用算法及存储在服务器端的秘钥获得签名,并与从客户端传来(token中)的签名对比,如果一致即已登录否则认证失败。
五、session和token的比较
1、session依赖于cookie,每次客户端访问服务器时都自动携带cookie,当使用前后端分离项目时,后台服务器不能获取到sessionId。即session不能跨域。
2、相反,客户端使用token时,每次访问都会在headers中添加token字符串,不借助于cookie。能够跨域。
# 普通的token
headers.Authorization = 'Bearer ' + token;
#JWT
headers.Authorization = 'JWT' + token;
3、使用session时,服务器在生成sessionId时,服务器端也会存储sessionId,当请求服务器的用户增多时,服务器开销巨大,同时严重限制了服务器的扩展能力。比如当服务器使用负载均衡时,小W使用A登录了服务器,访问B资源时会失败,因为B中没有小W的sessionId。(session sticky 请求黏着A,会存在A可能挂掉,然后仍然会转到B)。
只能使用session复制。麻烦。
如果把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 倘若负责session 的机器挂了, 所有人都得重新登录。
4、使用token时,服务器端不会存储token串或签名,客户端再次访问时会重新生成签名和携带的对比以校验用户。服务器节省了存储的空间压力,但是每次访问都需要重新计算签名。以服务的计算时间换取存储空间
5、使用token能够阻止CSRF攻击