B/S架构大家应该都不陌生,web1.0时代,用户通过个人电脑浏览网站,单项获取信息,比如我们浏览新闻,查阅资料等。web2.0很快就到来,和1.0相比,用户可以随时随地分享自己的信息。这个时候就涉及到了我们的身份认证。当我们使用http无状态请求访问资源服务的时候,服务端是如何知道我们的身份的,我们今天就来聊一聊。
传统方式的身份认证,我们要从cookie和session说起来,我们先回顾一下cookie和session是有什么特点吧。
Cookie:存储在客户端的,客户端专门存东西的一个标识。
1.能存储的东西很少,基本上只能存储4k左右的东西
2.能被手动清除,不续期的情况下,只有20分钟的有效期
3.Cookie安全问题,别人能从本地Cookie中获取信息
4.Cookie不能直接存储中文,如果需要,则需要进行url转码
5.不能跨域,不能跨域,不能跨域。
Session:存储在服务器端的,服务端专门存东西的一个标识。
1.安全性:Session的安全性比Cookie的安全性要高
2.性能:当服务器访问较多,比较占用性能
3.生命周期:异常关机会造成Session的销毁,默认存储30分钟
4.Session的钝化以及活化
钝化:服务器正常关闭后,tomcat会自动将Session数据写入硬盘的文件中
活化:服务器再次启动后,从文件中加载数据到Session中
5.浏览器关闭后再次重启SessionId的地址值不为同一个
4.访问范围:Session为一个浏览器共享
Cookie为多个浏览器共享
基于 cookie、session 的身份认证中,用户登录后,服务器会为登录用户创建一个 session,cookie的验证是有状态的,sessionid 会保存 在cookie 中。当用户登录成功后,之后的每次请求都会携带cookie。服务器通过 cookie 中的 sessionid 找到内存中的 session 数据,来验证用户身份,从而在响应中返回相应的数据。我们可以参照下图进行理解
这个图看着是没什么问题了对不,以前大多数B/S架构都采用这种实现方式,有的同学就说了:“我现在这么实现也ok啊,我干嘛还要去研究那个token呢?”,那你们可以想一想,当你的后端服务需要水平扩展的时候,你的session怎么办?当然我们也是有一些常规做法的。例如服务之间的session同步方案、分布式缓存方案、用户负载方案。我们一个一个来说。
1.session同步,就是在用户登录成功产生session之后,在你的各个服务上进行session同步,保证请求能够畅通访问其他服务,这个开销不得不说是很大的。
2.分布式缓存,将session存储在分布式缓存中,所有服务都从缓存中获取用户session。这是在集群中增加了中间件,代价也不小。
3.用户负载,这是一个偷奸耍滑的方案,通过nginx负载,将同一个用户的请求指向最初登录的那个服务器。
前面我们说了session方案需要考虑服务扩展问题,那么有没有更好的解决方案呢?这就得从我们的Jwt(json web token)说起了,现在流行的应用架构,很多都用使用jwt基于token实现身份认证的。什么是Jwt前面的文章有解释。那么如何实现呢,我们简单的说明一下token实现身份认证的步骤。
- 用户登录成功服务端返回token
- 之后每次用户请求都携带token,在Authorization Header中。
- 后端服务取出token进行decode,判断有效期及失效策略。
- 返回对应的成功失败
常用的token身份认证方案有两种,一种是单token方案,另外一种是双token方案。下面我们就来分别看图理解一下两种方案的认证及续期过程。
1.用户登录,服务端返回生成的Jwt,携带必要的信息。
2.用户再次访问时均需要在Authorization Header中携带Jwt。
3.服务端有配置好的token失效时间或者次数,还有重新登录期限。每次登录会记录当前登录时间。
4.用户携带token访问时,服务端根据token失效时间和重新登录期限判断返回对应代码
5.当token有效时,服务端返回对应资源。
6.当token失效时,前端拿到错误代码后重新请求refresh token接口进行token刷新,该接口会返回新的有效token给前端。
7.前端下次请求会携带刷新后的新token访问。
8.当某次访问时,服务端判断token使用时长超过了定义好的登录期限,则返回重新登录错误代码给前端,前端拿到代码后跳转至登录页面。
1.用户登录返回access_token、refresh_token。
2.用户请求资源时携带access_token。
3.当access_token有效时,返回对应的资源。
4.当服务端校验access_token失效,则返回对应错误代码。
5.前端拿到access_token失效对应的错误代码,发起刷新token请求,本次请求携带之前缓存的refresh_token。
6.服务端拿到refresh_token,判断是否有效,失效则返回重新登录错误代码。
7.前端拿到重新登录错误代码则跳转登录页面。
可以看到,使用token进行身份认证,不仅将服务端的存储压力分摊到了客户端上,并且可以让服务端进行毫无顾及的扩展,除此之外也不存在跨域问题,对于移动端也更加友好,不仅如此,Jwt的加密使得这种方案在安全性上更上一层楼。因此,各位架构师们,这是一种不得不掌握的身份认证方案。
点赞收藏,富婆包养✋✋