1. Session和Cookie的区别
前言:Http无状态协议,是指协议对于交互性场景没有记忆能力。
1. 存储位置不同:
Session:服务端(服务器)
Cookie:客户端(浏览器)
2. 存储数据格式不同:
Session和Cookie存储的都是键值对(key-value entry),但存储的value类型不同
Session:value为对象,Object类型。这个对象本身需要实现序列化接口(Serializable)
Cookie:value为字符串,如果要存储对象,就需要将对象转换为JSON格式(用Cookie难以存储略微复杂的信息)
3. 存储数据大小不同:
Session:因存储于服务端,大小受服务器内存控制。对于Session并没有上限,但出于对服务器端的性能考虑,Session内不要存放过多的东西,并设置session删除机制
Cookie:通常情况,单个Cookie保存的数据≤4KB,一个站点最多保存20个Cookie。
4. 生命周期不同:
Session:服务端控制,默认30分钟。倘若用户关闭浏览器,session也不会消失
Cookie:客户端控制,本质是一个客户端的文件,分两种情况:
a. 会话级的cookie(默认),随着浏览器的关闭而关闭,比如保存sessionId的cookie
b. 非会话级的cookie,通过设置有效期来控制,比如“7天免登录”功能,需要设置有效期,setMaxAge。这种cookie本身不会随着浏览器的关闭而关闭
注意:cookie的设置之一:httpOnly=true 防止客户端的XSS(Cross Site Scripting,跨站脚本攻击)攻击。
XSS:这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。比如可以获取用户在当前网站的cookie。
应对:1. 在后端进行一些Filter过滤,防止这类型的脚本攻击。2. 设置cookie参数:httpOnly=true。攻击者不能通过document.cookie拿到用户的cookie。httpOnly=true本身意思:只允许通过HTTP请求从后台获取,而不允许document.cookie这类方法。
5. 服务器压力不同
Session:Session都是存储在服务器上的,每个用户都会产生Session,假如并发的用户数量非常多,将产生非常多的Session,耗费大量服务器内存资源。可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
Cookie:保存在客户端,不占用服务器资源,适用于并发量很大的网站。
2. Session和Cookie的关联
HTTP协议是一种无状态协议,为了记住用户的状态,采用Session的机制,而Session的机制是:服务器会生成会话级别的cookie来保存session的标识,原来如下图:
- 用户第一次登录时,服务器端在内存中新建一个session,每个session都有一个sessionId,并且对该session调用
session.setAttribute()
来设置user - 当用户之后再打开网页时,调用
session.getAttribute("user")
就可以查到是否是有效的user。但系统不知道这个user是否是有效的,是否能对得上,所以需要检查sessionId是否匹配,这里就需要用户把自己的sessionId也一起发过来,否则系统检查一个会话需要的开销比较大。 - 用户因为需要携带这个sessionId,所以服务器本身也会给用户一个会话级别的cookie,如上图,
cookie(JseesionId, sessionId)
。访问时把cookie给服务器,服务器在内存中检查对应session,实现登录。
注意:如果在网站上把cookie禁止,很多网站就无法登录。
3. Token
3.1 传统方式的问题
传统基于服务器验证中存在的问题:
- Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。
- 可扩展性(最突出):在服务端的内存中使用Seesion存储登录信息,伴随而来的是可扩展性问题。
- CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。
3.2 Token特性
- 无状态、可扩展
- 支持移动设备
- 跨程序调用
- 安全
3.3 验证原理
基于Token验证的原理:
Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中,过程如下:
- 用户通过用户名和密码发送请求
- 程序验证。
- 程序返回一个签名的token 给客户端
- 客户端储存token,并且每次用于每次发送请求
- 服务端验证token并返回数据
- 客户端每次访问API是携带Token到服务器端
- 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码
3.4 Tokens的优势详解:(引用彻底理解cookie,session,token)
3.4.1 无状态、可扩展
在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。
如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成一些拥堵。
但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。
(这里其实没有理解,token同样需要服务器进行验证,存储这些token同样可能成为问题)
3.4.2 安全性
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。
3.4.3 可扩展性
Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上
3.4.4 多平台跨域
…没理解,未来理解了再补上
参考引用: