传统的session+cookie登录是一种有状态 的登录
1、传统的session+cookie 流程
2、cookie
cookie是前端存储的一种,但相比于localStorage 等其他方式,借助HTTP头、浏览器能力,cookie可以做到前端无感知。一般过程是这样的:
cookie是维持HTTP请求状态的基石,是最便捷的维持HTTP请求状态 的方式。
3、Session
Session的具体内容都是存储在服务端,只是给客户端一个SessionId存在cookie。Session的存储方式有:
Session的分布式问题
通常服务端是集群,而用户请求会走负载均衡,不一定就能请求到登录时的服务端。一旦用户后续接口请求到的机器和之前登录请求的机器不一致,或者登录请求的机器宕机了,session就没用了
解决方式:
把所有用户的session集中存储,我们可以用独立的Redis或者普通数据库(推荐是Redis)或者消息队列 ,这就是分布式session:
4、缺点:
随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高
session存储在服务端,如果用户很多的话,服务端保存大量数据,增加服务端的压力
服务从单服务到多服务会面临session共享问题,要考虑分布式的问题
流程 :
优点 :
可以隐藏真实数据,避免明文传输。ie里存的是一个32位的uuid
使用于分布式/微服务,解决session共享问题
安全系数高
缺点 :
存在redis,必须依赖服务器,会占用服务器的资源
效率较低,不过比起传统的session+cookie好多了
JWT全程是 JSON WEB TOKEN,JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息 ,也可以增加一些额外的其他业务逻辑所必须的声明信息,该token也可以直接被用于认证,也可被加密
JWT的组成部分 :
使用JWT登录过程:
用户提供用户名和密码进行认证。在认证成功后,服务器会生成一个JWT,在其中包含用户的一些身份信息,并使用秘钥 对其进行签名。
服务器将生成的JWT返回给客户端。客户端通常将JWT存储在本地,例如在 localStorage 或者cookie中。
客户端在后续的请求中,在请求的头部或者其他合适的位置添加JWT作为身份验证凭证。一般使用Authorization头部
服务器在接收到请求时,会验证JWT的有效性以及签名。
在进行签名验证时,需要使用之前生成JWT时使用的相同的秘钥 ,否则将无法正确验证签名,导致JWT无效;
服务端会检查JWT的各种声明和标准字段,如签发人(issuer)、受众人(audience)、过期时间(expiration time)等。根据业务需求,服务端可以自行定义额外的声明字段。
如果验证通过,表示用户是合法的,并且可以使用JWT中包含的信息来进行身份验证和授权。
优点:
缺点 :
JWT如何保证不被篡改?
JWT使用签名 来防止被篡改。在生成JWT时,使用一个密钥对JWT的头部和有效负载进行签名。当服务端接收到JWT时,首先会对JWT进行解码,然后使用相同的密钥对解码后的JWT的头部和有效负载重新进行签名 。然后,将重新计算的签名与原始JWT中的签名进行比较。如果重新计算的签名与原始JWT中的签名不一致,说明JWT已被篡改,验证失败 。
通过使用签名来验证JWT的完整性,可以有效地防止JWT被篡改。任何对JWT进行篡改的尝试都会被服务端检测到。同时,由于JWT中包含了签名算法和秘密密钥,攻击者无法伪造一个合法的签名。需要注意的是,服务端验证JWT时,必须使用与生成JWT时相同的秘密密钥来进行签名验证,否则验证会失败。同时,为了增强安全性,应该选择足够强大的签名算法和秘密密钥,以防止密钥泄露和暴力破解的攻击 。
当业务线越来也多,就会有更多业务系统分散到不同域名下(不同的系统),就需要(一次登录,全线通用)的能力,这就是单点登录。
1、“虚假的单点登录”,使主域名相同
我们知道,cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie 。
因此,我们可以将web应用群中所有子系统的域名统一在一个顶级域名下,采用同域名共享cookie的方式。这样也能实现一次登录,全线通用。
但是共享cookie的方式存在众多局限:
所有的子系统域名要统一;
应用群各系统使用的技术要相同,并且共享cookie的方式是无法实现跨语言技术平台登录的
2、“真实”的单点登录
当主域名不同时,实现一次登录,全线使用,这才是真正的单点登录。在这种场景下,我们需要独立的认证服务,通常被称为 SSO(Single Sign On)
只有SSO有登录账号密码的功能,其他系统都没有。用户在SSO登录后,SSO就会存储一个用户的登录凭证(这个是全局会话),然后根据重定向过来的地址,颁发要访问的系统的ticket。比如用户是从A系统重定向过来的,就颁发一个A系统的ticket(局部会话),客户端带着这个ticket就可以访问A系统了;当用户要访问B系统时,B系统将它重定向到SSO,已经登录了,所以SSO直接颁发可以访问B系统的ticket,客户端带着这个ticket就可以访问B系统了。这样就实现了一处登录,全线使用
但是这样有一个问题,SSO放回的ticket,浏览器要如何存,因为有很多个域名下,如何才能在下次访问A系统时带上这个ticket?因为浏览器对跨域有严格限制,所以我们需要在A域下保存这个A的ticket
1、HTTP 是无状态的,为了维持前后请求,需要前端存储标记-----cookie
2、cookie 是一种完善的标记方式,通过 HTTP 头或 js 操作,有对应的安全策略,是大多数状态管理方案的基石
3、session 是一种状态管理方案,前端通过 cookie 存储 id,后端存储数据,但后端要处理分布式问题
4、token 是另一种状态管理方案,token 的编码技术,通常基于 base64,或增加加密算法防篡改;jwt 是一种成熟的编码方案,并且JWT实现了无状态登录,相较于传统的有状态登录,更加灵活,解放服务端
5、session 和 token 的对比就是「用不用cookie」和「后端存不存」的对比
6、单点登录要求不同域下的系统「一次登录,全线通用」,通常由独立的 SSO 系统记录登录状态、下发 ticket,各业务系统配合存储和认证 ticket