Cookie和JessionId和Session的id;
客户端每次向服务端发送请求的时候,服务端都会给客户端发送一个Session请求对象的id,用来标识这个用户,每次客户端访问服务端的时候,服务端会给客户端创建一个Cookie对象发送给客户端,而Session的id,就是保存在Cookie对象中的,命名为JSessionId,如下图:
等到下次客户端访问服务端的时候,客户端会带上Cookie对象,然后服务端拿到客户端的Cookie对象之后会取出里面的JSessionid,然后和服务器端的SessionId对比一下,看看是否有相同的,如果有相同的证明这个用户之前登录过;如果没有相同的,服务器端会再给客户端创建一个JSessionId然后保存到Cookie对象中发送给客户端。
Cookie对象是在服务端生成的,但是最后会保存到客户端;而Session对象一直保存在服务端。
什么是单点登录?单点登录就是有多个系统,在一个系统中登录之后,其他系统自动登录。
你比如京东用的就是单点登录,京东的首页如下图:
京东的首页又分出了一个购物车系统,如下图:
拿京东的这两个系统为例子,在任意的一个系统中登录之后,所有的系统自动登录。这就是单点登录。比如你在首页系统登录之后,你再进入购物车系统发现已经是登录状态。
Http是一种没有状态的协议,也就是它并不知道是谁访问应用,这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下面这个客户端再发送请求的时候,还得再验证一下。
解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务器端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的ID发送给客户端,客户端收到以后把这个ID存储在Cookie里(其实也就是JSessionId),下次这个用户再向服务端发送请求的时候,可以带着这个Cookie,这样服务端会验证一个这个Cookie里的信息,也就是验证一下JSessionId,看看能不能在服务器端找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。
上面说的就是Session,我们需要在服务器端存储为登录的用户生成的Session,这些Session可能会存储内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的Session。·
这种传统的认证中出现的问题:
Session每次认证用户发起请求时,服务器需要去创建一个记录存储信息。当越来越多的用户法请求时,内存的开销也会不断增加。
CORS(跨域资源共享),当我们需要让数据跨多台易懂设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。
使用基于Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
客户端使用用户名,密码请求登录,服务端收到请求,去验证用户名,密码,验证成功后,服务端会签发一个Token,再把这个Token发送给客户端,客户端收到Token以后可以把它存储起来,比如放在Cookie里或者Local Storage里,客户端每次向服务端请求资源的时候需要带着服务端签发的Token,如果验证成功,就向客户端返回请求的数据。
使用Token验证的优势:
无状态,可扩展,在客户端存储的Token是无状态的,并且能够被扩展,基于这种无状态和不存储Session信息,负载均衡均衡器能够将用户信息从一个服务传到其他服务器上。安全性,请求中发送token而不再是发送cookie,能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session的操作。
JWT是一种紧凑且自包含的,用于在多方传递JSON对象的技术。传递的数据可以使用数字签名增加其安全性。可以使用HMAC加密算法或RSA公钥/私钥加密方式。
紧凑,数据小,可以通过URL,POST参数,请求头发送。且数据小代表传输速度快。
自包含,使用payload数据块记录用户必要且不隐私的数据,可以有效的减少数据库访问次数,提高代码性能。
JWT一般用于处理用户身份验证或数据信息交换。
用户身份验证:一旦用户登录,每个后续请求都将包含JWT,允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小,并且能够轻松地跨不同域使用。
数据信息交换:JWT是一种非常方便的多方传递数据的载体,因为其可以使用数据签名来保证数据的有效性和安全性。
JWT的数据结构是:A.B.C。由字符点’.'来分隔三部分数据。
A-header头信息。
B-payload(有效荷载)
C-Signature 签名
数据结构:{“alg”:“加密算法名称”,“typ”:“JWT”}
alg是加密算法定义内容,如:HMAC SHA256 或RSA
typ是token类型,这里固定为JWT
在payload数据块中一般用于记录实体(通常为用户信息)或其他数据的。主要分为三个部分,分别是:已注册信息(registered claims),公开数据(public claims),私有数据(private claims)。
payload中常用信息有:iss(发行者),exp(到期时间),sub(主题),aud(受众)等,这些都是属于已注册信息。
公开数据部分一般都会在JWT注册表中增加定义。避免和已注册信息冲突。公开数据和私有数据可以由程序员任意定义。
注意:即使JWT有签名机制,但是payload内容都是明文记录,除非记录的是加密数据,否则不排除泄露隐私数据的可能。不推荐在payload中记录任何敏感数据。
签名信息。这是一个由开发者提供的信息。是服务器验证的传递的数据是否有效安全的标准。在生成JWT最终数据之前。先试用header定义的加密算法,将header和payload进行加密,并使用点进行连接。如:加密后的head加密后的payload。再使用相同的加密算法,对加密后的数据和签名信息进行加密。得到最终结果。
官网:jwt.io,如下图:
jwt一共包含三部分,第一部分是Header部分,这部分用来定义加密算法的类型,如下图:
第二部分是Payload,这部分主要是记录用户信息的,如下图:
第三部分是Signature签名部分,这部分主要是前两部分加密之后的结果。
jwt技术主要是用来生成token令牌的,首先给Header部分加密,然后给Payload部分加密,最后再给Header加密之后的结果和Payload加密之后的结果进行加密,生成我们的Token令牌值,如下图:
如下图:
总之就是,服务器首先看token,如果token没过期,服务端就让客户端登录;如果token过期了,但是refresh_token还没有过期,这个时候服务器也会让你登录,但是会给你客户端重新生成token和refresh_token;如果token和refresh_token都过期了,那么服务器不会让客户端登录。
使用JWT实现单点登录时,需要注意token时效性,token是保存在客户端的令牌数据,如果永久有效,则有被劫持的可能。token在设计的时候,可以考虑一次性有效或一段时间内有效。如果设置有效时长,则需要考虑是否需要刷新token有效期问题。
使用JWT技术生成的token,客户端在保存的时候可以考虑cookie或localStorage.cookie保存方式,可以实现跨域传递数据。localStorage是域私有的本地存储,无法实现跨域。
webstorage可保存的数据容量为5M,且只能存储字符串数据。webstorage分为localStorage和sessionStorage。localStorage的生命周期是永久性的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。
sessionStorage是会话相关的本地存储单元,生命周期是仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面。sessionStorage也是不一样的。