SSO 单点登录
概念
单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供存取控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的存取权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一退出(single sign-off)就是指,只需要单一的退出动作,就可以结束对于多个系统的存取权限。
From Wikipedia
定义
首先,先来对web系统中常见的概念做个定义。
认证 & 授权
这两个名词是属于安全领域的两个术语。也许因为他俩常常接近于同时发生,许多人就常常把他们混在一起。不过这里暂时不详细展开,先简单的确定一下定义,后面会单独开一篇来讲讲认证授权以及网络安全相关的内容。
认证 -> 你是谁
认证(身份验证),最常见的,就是通过用户名密码的组合来判断用户的身份,注意 认证只是为了让服务端知道,现在访问的人是谁?仅此而已。而通常来说,用户在浏览过程中,不可能每一个操作都要重新输入用户名密码,太麻烦了。于是服务器验证用户身份后,会颁发一个用户凭证(Token)给用户,用户下次访问的时候,带上这个凭证,服务器就可以知道这个人是谁。
授权 -> 你能做什么
授权:授予一个人做某事的权力,或者说 检查某个人是否有使用某个资源的权限。
通常是在认证后发生,服务器通过认证知道在访问的人的身份,之后在授权用户权限,比如能不能看这个页面,能不能查这个数据?
Session 会话
HTTP请求是无状态的,对于每一个请求,又需要知道对应的是哪个用户,于是就有了Session,来保持服务端和用户的联系。最基础的,各个web框架默认自带的就是服务器内存中存储session和浏览器cookie中保存sessionid的方案。
单点登录
现在我们再来讲讲单点登录。
单点、登录。说明有多个点(多个服务),但只要在一个点,登录一次,多个点即共享登录状态。
比如淘宝和天猫,都知道他们共属于阿里巴巴,但是从架构上,他们是不同的服务,从网络上,他们是不同的域名(tmall.com / taobao.com),存在跨域。不过大家也都知道这两个网站,只需要登录其中一个,另一个自然也是登录状态,不需要同时登录。
多系统,每个系统可能是部署在不同的服务器上,有各自独立的服务器、数据库,每个服务的域名也可能不同。
这样在异构且跨域的系统间共享登录状态,就是SSO解决的问题。
统一登录的本质,就是如何保存和获取Session
传统的登录,由于session保存在单个系统的内存中,所以多个系统间不能共享用户状态,而解决方案,本质就是让每一个系统都能取到session。
一般的方案有:
- 服务间全局复制session,即每个服务都保存一个全量的用户会话,并完全同步。
- 统一存储,把所有的用户会话都放到一个服务中,每个系统都从这里获取用户信息。
- 使用redis代替服务来存储,每个服务都从redis里查询。
- 使用JWT等方案,将session的部分内容分散到token本身,服务端不存储状态。
1 就不说了,几乎没有优势,同步和性能来说都不怎么样。
2 就是常见的单点登录方案,一般使用 apereo cas 来当这个统一认证服务,各个子系统对接cas。简单点说,就是所有登录操作都在cas上完成,登录成功后,在cas上保存用户session并生成令牌,登录成功后,带着令牌将用户前端重定向到跳转前的子系统,系统从url中获取令牌并保存,在验证登录状态时就使用这个令牌向cas查询和验证。
3 比较简单,开发起来比较方便,就是多系统间不方便拓展,容易有冗余。
4 也是比较常用的方案,它的优点同时也是缺点,由于将用户信息直接保存在用户端,后端通过对jwt中的信息和签名进行校验,可以实现真正意义上的无状态http请求,而缺点就是,不能在后端实现对用户状态的主动管理,比如使签名失效,强制下线等。有人就会说,在后端保存一下用户信息,强制下线的时候改一下状态不就可以了吗?仔细想想,这样处理,不是又退化成了传统的session形式了吗?
总结
以上简单的讲了一下我对于单点登录的理解和一些方案,实际项目中,还是那句老化,没有最好的方法,只有最合适的,每个方案都有自己的优缺点,应该结合项目情况来进行选择。