目录
前置知识
Cookie
什么是Cookie
Cookie的作用
Cookie的声命周期
Session
什么是Session
服务集群下Session存在的问题
集群模式下Session无法共享问题的解决
Cookie和Session的对比
Token
什么是Token
为什么产生Token
基于JWT的Token认证机制
Token的优势
参考链接
前置知识
无状态协议HTTP
无状态:协议对于事物处理没有记忆能力。缺少状态意味着,假如后面的处理需要前面的信息,则前面的信息必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要前面信息时,应答就较快。直观地说,就是每个请求都是独立的,与前面的请求和后面的请求都是没有直接联系的。
HTTP协议为什么是无状态的:HTTP协议的设计的初衷是用来浏览静态文件的,无状态协议就已经足够了,这样实现的负担也小。实现有状态的代价比较大,需要维护状态,根据状态来进行操作。
HTTP协议无状态产生什么问题:HTTP 协议是无状态的,这种无状态意味着程序需要验证每一次请求,从而辨别客户端的身份。同时HTTP协议无状态的,使得各个请求之间没有任何联系,无妨访问上一个HTTP请求的相关数据。
Cookie
什么是Cookie
Cookie就是一些数据,用于存储服务器返回给客服端的信息,客户端进行保存。在下一次访问该网站时,客户端会将保存的cookie一同发给服务器,服务器再利用cookie进行一些操作。
Cookie只支持浏览器,不支持app端。
Cookie的作用
自动登陆:我们在 Cookie
中保存已经登录过的用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外,Cookie
还能保存用户首选项,主题和其他设置信息。
保存历史记录:Cookie
还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为 HTTP 协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在 Cookie中。
身份认证:使用 Cookie
保存 SessionId
或者 Token
,向后端发送请求的时候带上 Cookie
,这样后端就能取到 Session
或者 Token
了。这样就能记录用户当前的状态了。
Cookie的声命周期
- 会话性:如果cookie为会话性,那么cookie仅会保存在客户端的内存中,当我们关闭客服端时cookie也就失效了
- 持久性:如果cookie为持久性,那么cookie会保存在用户的硬盘中,直至生存期结束或者用户主动将其销毁。
Session
什么是Session
Session在网络应用中称为“会话控制”,是服务器为了保存用户状态而创建的一个特殊的对象。简而言之,session就是一个对象,用于存储信息。
服务集群下Session存在的问题
在集群模式下我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。
集群模式下Session无法共享问题的解决
- 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
- 每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
- 单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点。
使用Redis存储Session Id结构图
Cookie和Session的对比
- cookie保存在客户端,session保存在服务端
- cookie作用于他所表示的path中(url中要包含path),范围较小。session代表客户端和服务器的一次会话过程,web页面跳转时也可以共享数据,范围是本次会话,客户端关闭也不会消失。会持续到我们设置的session生命周期结束(默认30min)
- 我们使用session需要cookie的配合。cookie用来携带JSESSIONID
- cookie存放的数据量较小,session可以存储更多的信息。
- cookie由于存放在客服端,相对于session更不安全
- 由于session是存放于服务器的,当有很多客户端访问时,肯定会产生大量的session,这些session会对服务端的性能造成影响。
- Cookie不能跨域【跨域:协议、IP、端口三者任意一个不同均属于跨域】
Token
什么是Token
Token是“令牌”的意思。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
为什么产生Token
参考:
于是有人就一直在思考, 我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?
可是如果不保存这些session id , 怎么验证客户端发给我的session id 的确是我生成的呢? 如果不去验证,我们都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造session id , 为所欲为了。
嗯,对了,关键点就是验证 !
比如说, 小F已经登录了系统, 我给他发一个令牌(token), 里边包含了小F的 user id, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。
Token的产生就是让登陆认证的相关信息由服务端生成后发送给客户端,之后客户端登陆的时候自动携带上登陆认证相关信息(Token),无需服务端存储相关信息,从而解决分布式情况下共享Session Id的问题。
基于JWT的Token认证机制
JWT:一种规范化之后的JSON结构的基于Token的认证授权机制。
- 组成:
- Header:定义生成签名的算法以及Token的类型。
- PayLoad:存放实际需要传输的数据。
- Signature:服务器通过Header、PayLoad以及密钥根据Header里面指定的签名算法生成的。
基本格式:xxxx.yyyy.zzzz
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.JTdCJTIybmFtZSUyMiUzQSUyMlRvbSUyMiUyQyUyMmlhdCUyMiUzQTE1MTYyMzkwMjIlN0Q=.SflKxwRJSMeKKF2QT4fwpMeJ
用途——基于JWT进行身份验证
1.用户向服务器发送用户名、密码以及验证码用于登陆系统。
2.如果用户用户名、密码以及验证码校验正确的话,服务端会返回已经签名的 Token,也就是 JWT。
3.用户以后每次向后端发请求都在 Header 中带上这个 JWT 。
4.服务端检查 JWT 并从中获取用户相关信息。
如何防止JWT被篡改:保管好密钥,不要泄露出去。JWT安全的核心在于签名,签名的核心在于密钥。
Token的优势
- 无状态、可扩展:在客户端存储的 token 是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载均衡服务器 能够将用户的请求传递到任何一台服务器上,因为服务器与用户信息没有关联。相反在传统方式中,我们必须将请求发送到一台存储了该用户 session 的服务器上(称为Session亲和性),因此当用户量大时,可能会造成 一些拥堵。使用 token 完美解决了此问题。
- 支持移动设备(可以作为面试的一个回答点)
- 跨程序调用:暂时不懂,以后不上。
- 安全:请求中发送 token 而不是 cookie,这能够防止 CSRF(跨站请求伪造) 攻击。即使在客户端使用 cookie 存储 token,cookie 也仅仅是一个存储机制而不是用于认证。另外,由于没有 session,让我们少我们不必再进行基于 session 的操作。 Token 是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过 token revocataion可以使一个特定的 token 或是一组有相同认证的 token 无效。
参考链接
Session详解,学习Session,这篇文章就够了(包含底层分析和使用)_session级别-CSDN博客
什么是token?token是用来干嘛的?_token是什么意思-CSDN博客
基于Token的身份验证的原理 - valentin - 博客园 (cnblogs.com)
认证授权基础概念详解 | JavaGuide