什么是SSO?
单点登录(Single Sign On,简称 SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权,无需再次登录。这种技术目前得到了广泛使用,它核心解决了一个问题:用户只需要登录一次,就可以访问所有相互信任的应用系统。SSO是一种思想,或者说是一种解决方案,是抽象的,我们要做的就是按照它的这种思想去实现它。
举个例子:
我在这边已经登录了QQ空间 https://qzone.qq.com , 当我们再打开QQ邮箱时发现并不需要登录了 https://mail.qq.com
传统的多点登录系统中,每个站点都实现了本站专用的帐号数据库和登录模块。各站点的登录状态相互不认可,各站点需要逐一手工登录。如下图,有两个术语含义如下:
SSO有什么好处?
说到这里,你可能会问为什么我们需要实施 SSO 呢?原因很简单,因为它提供了很多优势。下面我们具体分析一下。
首先,借助 SSO 可以确保系统更加安全,我们只需要一台集中式服务器来管理用户身份,而不需要将用户凭证扩展到各个服务,因此能够减少被攻击的维度。
其次,可以想象持续输入用户名和密码来访问不同的服务,是一件让用户感到很困扰的事情。而 SSO 将不同的服务组合在一起,以便用户可以在服务之间进行无缝导航,从而提高用户体验。
同时,SSO 也能帮助我们更好地了解客户,因为我们拥有对客户信息的单一视图,能够更好地构建用户画像。
单点登录设计与实现
单点登录模式 |
优点 |
缺点 |
共享Cookie模式 |
简单方便,用户体验好 |
根域名需限制一致;Cookie可能不安全 |
OAuth2.0模式 |
灵活安全,不受站点限制 |
成本稍高,需独立的认证中心 |
跨域设置Cookie |
用户体验好,不受站点限制 |
比较麻烦;Cookie可能不安全 |
客户端模式 |
用户体验好,不受站点限制 |
成本极高,依赖于用户本地安装客户端应用 |
OAuth2模式实现单点登录
采用 Spring Security 和 OAuth2 协议是一个不错的选择,因为实现过程非常简单。虽然 OAuth2 一开始是用来允许用户授权第三方应用访问其资源的一种协议,也就是说其目标不是专门用来实现 SSO,但是我们可以利用它的功能特性来变相地实现单点登录,这就需要用到 OAuth2 四种授权模式中的授权码模式。同时,在使用 OAuth2 协议实现SSO时,我们也会使用 JWT 来生成和管理 Token。
多个站点共用一台认证授权服务器(用户数据库和认证授权模块共用)。用户经由其中任何一个站点(比如 北冥网站-A
)登录后,可以免登录访问其他所有站点。而且,各站点间可以通过该登录状态直接交互。
OAuth2实现原理分析
流程解析
- 站点1发现用户未登录时,跳转至认证中心
- 认证中心发现用户未登录(Cookie中没有认证记录),显示认证中心的登录页面
- 用户输入账号密码登录,认证成功后,前端记录认证信息保存后端返回的accessToken令牌(可通过令牌获取对应用户名username),后端redis存入access_token对应信息,其key为username:站点1的clientId,返回站点1的access_token
- 认证中心携带access_token跳转至站点1的回调地址
- 站点1前端获取到access_token令牌,记录已登录状态,每次请求携带access_token
- 站点2发现用户未登录时,跳转至认证中心
- 认证中心前端判断已认证授权过:从前端Cookie中取出存储的accessToken(可通过令牌获取对应用户名username)
- 认证中心调用已授权验证接口,先验证accessToken是否有效,若有效,则后端Redis存入新站点的access_token信息,其key为username:站点2的clientId,返回站点2的access_token
- 认证中心携带access_token跳转至站点2的回调地址
- 站点2前端获取到access_token令牌,记录已登录状态,每次请求携带access_token
注销流程分析示例
任一站点用户退出登录,通过Redis失效所有以username开头的键值对即可