传统网页登录
最简单的登录方式,是在每一次使用系统的时候进行身份的鉴定,一旦认证信息过期了,便跳出登录界面,让用户输入用户名和密码。
将用户名和密码通过加密处理后,发到后端进行登录认证。后端会依据此次会话的时间、用户的信息创建一个session id,将session id看作是此次会话的唯一标识。并将session id写到cookie中,在每一次的请求中都携带过去,以认证用户的身份。
但是这样有三个问题,
- 一是,如果是公司内部的服务,每个系统都有一个登录模块,使用者就要在每一次使用系统的时候都进行登录操作,记住每一个系统的账号和密码,这样实在没有必要。
- 二是,如果后端的服务器不止一个怎么办,登录时创建的session id存储在登录的服务器上,但是某一次请求如果被打到其他服务器上,其他服务器并不知道上下文,如何判断用户信息呢?
- 三是,将身份认证存储在cookie中会不会带来一些隐藏的问题
正是因为有了这些问题,才有了后续针对问题解决办法。
单点登录
考虑到第一个问题,公司内部服务多采用单点登录,即一次登录便可访问所有的互相信任的系统。
这种只需要登录一次的解决方法,叫做单点登录(single sign on)。
SSO的核心是通过共享cookie中的session id做到的。
假设A系统使用的是SSO系统提供的登录认证。
- 当访问A系统的后端数据时,判断请求的cookie中是否含有session id
- 如果有,则携带session id去请求后端的接口,后端通过请求中的session id认证用户信息。
- 如果没有,则通过302重定向到SSO页面,进行用户的登录。
- 如果用户没有在SSO系统上登录过,则跳转到SSO系统的login界面进行用户的登录。
- 如果用户在SSO系统中登录过,则将用户对应的ticket granting ticket拼接到重定向到login的url(也就是1中访问A系统的后端接口)上再次访问。
- 这时A系统的后端就接收到了一个含有ticket的请求,A后端访问SSO后端提供的校验接口进行ticket的认证,判断请求的真伪。
- 如果用户信息校验为真,则由A后端根据用户信息、时间等构造session-id并set-cookie。
- 如果用户信息校验为假,则进行相应的报错,或是再重定向到SSO进行再次登录。
具体CAS流程图如下:
更详细的SSO流程解释可参考阿里云上的单点登录(SSO)看这一篇就够了-云栖社区-阿里云yq.aliyun.com
JWT登录
不管是否使用了SSO,针对用户的信息的鉴定和存储都是通过session id去实现的。
这样会存在上面说到的后两个问题,展开来说应该有三个:
- 通过session id进行鉴权,需要在服务器上额外存储信息,进行session id和用户表的关联,增加数据库负担
- 如果后端对应多个服务器,通过负载均衡等方式,进行请求的分配,如果在每一个服务器上都存储session id和用户信息的对应关系,不但会增加数据库的负担也增加了服务器之间不必要的通信,无疑是不合适的;但是如果不进行信息的存储,则服务器无法进行鉴权。
- session id存储在cookie中
- 一来,会导致安全问题,cookie是可见的,可以被其他用户冒用,如CSRF攻击
- 二来,会收到针对cookie的一些跨域策略的限制,如sameSite等
因此,综合考量,可以使用JWT方式进行鉴权,以避免上述问题。
JWT
JWT,即json web token,首先能明确的一点是这个token本质上是一个json格式的数据。
JWT分为三个部分:
- 头部 header
- 说明加密的应用在signature中的加密算法
- 有效载荷 payload
- 用户信息等
- 认证信息 signature
- 前两个信息的加密
对应的使用JWT有以下几个好处
- 当服务器有多个,通过负载均衡进行请求的分配时,不需要考虑session id与用户信息的对应关系,拿到token进行鉴权和解析即可。
- 一来,不需要考虑session id的存储问题,减少了存储负担和每次解析请求的查询负担。
- 二来,由于没有session id的对应关系了,所以在分布式机器的情况下更适用。根据对应字段直接鉴权,解析即可。
- 当使用单点登录,后端在做鉴权的时候,不需要拿到ticket之后再去与SSO的后端进行交互,可以直接通过SSO系统中提供的公钥进行信息的鉴权,减少了后端与SSO系统交互的过程。
- 通过JWT构成的token可以放在cookie里也可以放在http头中,放在header里可以避免因为cookie限制导致的隐形问题。
JWT只是一种方法,可以用于单点登录,也可以用于单一系统,差别仅是JWT的token是SSO系统生成还是该单一系统后端生成而已。
更多详细的JWT内容可见JWT官网jwt.io
总结
随着场景的变化,登录的情况越来越复杂。
由于希望同个公司的多个系统不需要多次重复登录所以出现了「单点登录」的方式。
由于考虑到session id存储带来的额外负担,因此出现了JWT的登录方式。
随着Chrome对cookie限制的提高(文章网络安全中开发案例的描述),将session id登录方式改为JWT已经变成了一种趋势。