# SSO单点登录 `SSO`单点登录是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。 ## 实例 最初的时候,服务的提供者只做了一个单系统,所有的功能都在单系统上,此时不需要`SSO`,一次登录就可以访问所有功能,后来用户量越来越大且功能服务越来越多,为了合理利用资源和降低耦合性,服务商将功能划分为多个子系统,而子系统的用户登录凭证是相互隔离的,如果在这个子系统登录完成,再访问另一个子系统还需要登录,这显然不太合适,而`SSO`就是对于这种问题的解决方案,在多个系统中,用户只需要某一个系统中登录,在其他系统中都无需再次验证用户身份即可静默登录,例如在百度一次登录,再访问贴吧、网盘等都可以静默登录。 ### OAUTH与SSO区别 * 从信任角度来看,`OAUTH`开放授权的服务端和第三方客户端不属于一个互相信任的应用群,而单点登录`SSO`的子系统都在一个互相信任的应用群,通常是同一个公司提供的服务。 * 从资源角度来看,`OAUTH`开放授权主要是让用户自行决定在服务端的个人资源是否允许第三方应用访问,资源都在`OAUTH`服务提供者那一方,客户端是想索取用户的资源,而单点登录`SSO`的资源本身都在子系统这边,而不是在`SSO`服务器这一方,主要服务是用于登录,以及管理用户在各个子系统的权限信息。 ## 实现方案 ### 共享SESSION 如果系统是使用`SESSION`来记录用户信息的话,那么就可以采用共享`SESSION`的方式进行实现单点登录,使用`SESSION`信息作为单点登录的方式就需要解决两个问题,一是子系统的`SESSION`是相互隔离的问题,二是用户的`SESSION-ID`如何在客户端共享的问题。 `SESSION`的一致性的解决方案主要有`SESSION`同步、`SESSION`集中存储的方式,`SESSION`同步比较消耗资源,所以一般还是使用`SESSION`集中存储的方式。 对于`SESSION-ID`在客户端共享的问题,`SESSION-ID`主要还是存储在`COOKIE`中,所以需要解决的问题是`COOKIE`的跨域问题,对于同一个顶级域名下的二级域名,可以通过在`SET-COOKIE`时设置`domain`属性为顶级域名,即可实现在顶级域名与二级域名三级域名下的`COOKIE`共享,若是需要非子域名下的`COOKIE`共享,可以考虑使用`P3P`隐私参考项目平台`Platform for Privacy Preferences`的`header`的方式跨域`SET-COOKIE`。 ### Ticket `Ticket`方式也称为`SSO-Token`,其是一个用户身份的标识,这个标识在所有子系统群中是唯一的,并且所有的子系统`SERVER`都可以验证这个`Token`并同时能够拿到这个`Token`所代表的用户信息,同样这种方式也需要解决`COOKIE`的跨域问题,同样一般也是需要使用顶级域名的`domain`属性或者`P3P`的`header`的跨域`SET-COOKIE`。 ### CAS `CAS`中央认证服务`Central Authentication Service`,将认证服务单独抽出作为一个子系统,所有的登录认证服务都在`CAS`认证中心进行。`CAS`系统像是一个中转中心,可以认证所有用户的身份,同样也可以直接通过在`CAS`系统登录后以登录态跳转到其他各个系统。 假如我们存在三个子系统,`A`系统`A.com`、`B`系统`B.com`、认证服务`SSO.com`,当用户已经注册,登录时的主要流程: * 用户打开系统`A`,此时用户未登录,系统自动跳转到认证服务系统`SSO.com`并携带参数存储跳转地址`A.com`。 * 用户在`SSO.com`输入账号密码,点击登录验证成功后,中央认证服务器返回一个`Ticket`,并将已经登录的`COOKIE`写入`SSO.com`认证服务的域名下,`SSO.com`认证服务重定向至跳转到认证服务时携带的地址,也就是上一步的`A.com`,并携带中央认证服务端下发的`Ticket`。 * 系统`A`得到`Ticket`并向本系统的服务器传递`Ticket`,服务端验证`Ticket`无误后获取`Ticket`中携带的用户信息,并设置当前`A`系统的此用户为登录态,下发`COOKIE`信息等用户凭据,至此该用户可正常使用`A`系统的服务。 * 此时用户打开`B`系统,由于用户未在`B`系统登录,系统自动跳转到认证服务系统`SSO.com`并携带参数存储跳转地址`B.com`。 * 用户在`SSO.com`已经处于登录状态,此时直接从中央认证服务器获取`Ticket`,然后重定向至跳转到认证服务时携带的地址,也就是上一步的`B.com`,并携带中央认证服务端下发的`Ticket`。 * 系统`B`得到`Ticket`并向本系统的服务器传递`Ticket`,服务端验证`Ticket`无误后获取`Ticket`中携带的用户信息,并设置当前`B`系统的此用户为登录态,下发`COOKIE`信息等用户凭据,至此该用户可正常使用`B`系统的服务。 ## 每日一题 ``` https://github.com/WindrunnerMax/EveryDay ``` ## 参考 ``` https://www.zifangsky.cn/1327.html https://zhuanlan.zhihu.com/p/66037342 https://www.jianshu.com/p/75edcc05acfd https://blog.csdn.net/qq_32060101/article/details/83473760 https://blog.csdn.net/qq_32239417/article/details/62228624 https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie ```