SSO英文全称Single Sign On,单点登陆。当咱们搜索单点登陆
的时候,会发现不少的文章,然而这些文章通常都是基于一种通用的场景描述,一般在各自的业务环境会更加复杂。在本篇文章,我将描述具体场景下实现单点登陆的方案。html
SSO英文全称Single Sign On,单点登陆。SSO是在多个应用系统中,用户只须要登陆一次就能够访问全部相互信任的应用系统。它包括能够将此次主要的登陆映射到其余应用中用于同一个用户的登陆的机制。它是目前比较流行的企业业务整合的解决方案之一。前端
企业发展初期,通常一个域名站点即可承载独立业务。但随企业对于新业务的探索,便都会申请一个新的域名用于这部分新业务的功能承载,一方面是为了作区分,另外一方面是知足监管的要求。而且须要在这种模式下打通原先站点的用户体系。新的独立域名主要有两种:webpack
对于第一种场景,通常咱们采用共享session
的方式就能够作到用户在不一样域名之间跳转而无需重复登陆。具体实现主要是将cookies
中关于用户登陆态的sessionid
的domain设置为.a.com
。web
这种场景较为简单,实现上作好新老模式之间的切换便可。由于默认状况下sessionId的domian是www.a.com
,若是以前已经访问过www.a.com站点,且登陆的时候未清除掉domian为www.a.com
的sessionid,那么访问www.a.com
的站点,浏览器会把两个同名sessionId传递到服务端,因为是key-value
的形式,服务端没法分辨哪一个是新的,哪一个是旧的,若是取了旧的,那么就没法获取用户此时登陆状态。解决这个问题,只须要在设置sessionId的时候把原有domian为www.a.com
的置为过时,或者用一个新的sessionId键便可。具体查看set-cookies介绍。redis
这种场景在咱们的移动站点用的比较多。例如主站www.a.com,移动站点为m.a.com这种场景。npm
#设置domian为.a.com的sessionId
Set-Cookie: sessionId=a3fWa; Domain=.a.com; Secure; HttpOnly
#将domian为www.a.com的sessionId置为过时
Set-Cookie: sessionId=a3fWa; Domain=www.a.com; expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly
复制代码
接下来咱们主要描述第二种场景。对于这种场景,主要要求是用户无感知,须要作到如下几点:跨域
以上是主动同步登陆态的时序图。图示中的ticket主要存放在redis
中,你也能够存放在其余的存储媒介甚至应用运行内存,可是须要注意的一点就是ticket应一次有效,用过以后须要清除掉。因为这里咱们的b站点也在本身的受控范围,而且redis的读写性能也至关优越,因此a和b链接并读取了同个redis。若是b站点不在受控范围内,可在b站点后台发起一个请求到a站点询问ticket的有效状态。具体流程以下:浏览器
因为a、b站点相互独立,假设各自的session过时时间为半小时,若是a站点一直处于访问状态,那么session会一直续命下去,可是b站点因为超过30分钟没有访问,session状态已通过期,这时候访问b站点就会有这个场景了。具体流程以下:安全
同流程二,这个场景的出现也是由于长时间未访问登陆b站点致使,与流程二不一样的是,这个场景是302直接跳转同步页面的方式,由后台直接判断,适合后台直出页面,若是是纯静态页面请使用流程二,具体流程以下:bash
以上流程主要在于实现SSO过程的针对各类场景的解决方案,根据经过发起方的不一样又可分为两类,主动同步和被动同步。主动同步是向认证站点获取ticket并同步自身登陆态,被动同步是由认证站点向当前站点同步登陆态。
通常网上的资料会有一个专门用做认证登陆的站点,好比a.com和b.com站点都从sso.a.com获取认证状态。其实在本文中就是把a站点用做sso站点了,原理上是一致的。
为了这一套方案落地的时候,业务开发同事无需关注这部分实现细节并编写相应的同步代码,咱们把他写入了总体框架里面,主要作了一下两件事:
更多关于sso认证方面的能够参考OAuth2的流程,这套流程用于不可信站点之间的认证在安全方面会更加成熟些,也是目前微信采用的认证流程。
FYI: