SSO单点登录


多系统登录问题

传统的登录方式要求用户在每个应用系统中都输入用户名和密码进行登录,这样不仅繁琐,还会增加用户的负担。比如 你有 100个系统,你可能会有一百个域名,每个系统都有一个登录页面,这样你就有一百个登录页面,不同的系统你可能有不同的登录方式,也可能有不同的账号密码,这时候从一个系统切换到另一个系统你就得输入一百次账号密码。

用户中心

为了解决这类问题,首先是账号的问题,你在不同系统中的账号必须是相互关联的,不能说你在 A 系统的账号是 Alice 你在 B 系统的账号是 Ali , 此时没有人知道 Alice 和 Ali 都是你,更何谈单点登录呢。由于这些系统互相独立,且每个系统都需要识别用户的身份,并根据用户的身份来进行权限控制。如果每个系统都各自实现用户管理和认证的功能,就会带来用户信息冗余、不同步等问题,也会导致用户必须记住每一个系统的用户名和密码,从而给用户带来不少麻烦。例如,用户同时使用某个大型企业内部的10个应用系统,就必须在这10个应用系统中都创建自己的账户并记住账户,这样每个系统都需要管理用户的信息,而且一旦用户在某个系统中修改了信息,就会导致系统之间用户信息不一致的问题。万一系统的数量增加到50个、100个了?估计企业和用户都要疯了。
解决上述问题的根本方法是建立统一用户中心,存储、维护、管理所有应用系统的用户信息,首先确保了使用同一套账号密码。
用户中心的职责:

  1. 用户信息的存储、维护、管理等功能。
  2. 用户身份识别、角色分配等功能。

sso 定义

统一用户管理系统能够很好的解决用户信息冗余和不同步的问题,也能减轻用户需要创建并管理多个账户的痛苦,即使这样也仍然存在多个系统都需要用户登录的问题。例如,用户同时使用某个大型企业内部的10个应用系统,那么就需要用户使用同一个账号信息去分别登录每个系统,这样的操作必定会导致用户体验太差。单点登录就是为了解决这个问题而提出的。

注意:单点登录是为了解决同一用户在使用多个系统时的重复登录的问题。

维基百科

单一登入(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软体系统,提供存取控制的属性。当拥有这项属性时,当使用者登入时,就可以取得所有系统的存取权限,不用对每个单一系统都逐一登入。这项功能通常是以轻型目录访问协议(LDAP)来实作,在伺服器上会将使用者资讯储存到LDAP资料库中。相同的,单一登出(single sign-off)就是指,只需要单一的登出动作,就可以结束对于多个系统的存取权限。
百度百科
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是比较流行的。

我觉得百度百科的解释可能更贴切些。注意 sso 是一种思想,他并不是一种具体的实现。就跟 LDAP 一样,他只是一个协议,而OpenLDAP才是它的具体实现一样。 sso 有好几种实现方式,但所有的实现都会用到令牌,对令牌的不同使用方式就诞生了不同的sso实现手段,网上怎么叫的都有,也没有一个统一的标准。其实所谓的单点登录就是对令牌的共享,只要各个系统都认你这一套令牌,那我就默认你自动登录了。

要想实现单点登录 首先必须 得有 上面说的 统一的 用户中心。其次还得有一个统一 认证中心,用来干 认证 凭证 的事情。因为如果 十个 系统有 十个登录页面,这明显是重复劳动,于是我们先把 这十个 页面 统一 成一个页面,所有系统的登录都从这个页面开始。

令牌的玩法如下

基于CAS的SSO

这个页面要能实现

  1. 用户登录后能够记住已经登录过
  2. 在确认用户已经登录过后,自动跳转到各自系统地页面
  3. 要能让各自系统知道当前用户的信息
    上面三个功能是最基础的,此外这些功能必须保证安全,信息不泄露

Alt text
上图是CAS官网上的标准流程,具体流程如下:

用户访问app系统,app系统是需要登录的,但用户现在没有登录。
跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
验证通过后,app系统将登录状态写入session并设置app域下的Cookie。
至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

用户访问app2系统,app2系统没有登录,跳转到SSO。
由于SSO已经登录了,不需要重新登录认证。
SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
app2拿到ST,后台访问SSO,验证ST是否有效。
验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。
这样,app2系统不需要走登录流程,就已经是登录了。SSO,app和app2在不同的域,它们之间的session不共享也是没问题的。

SSO系统登录后,跳回原业务系统时,带了个参数ST,业务系统还要拿ST再次访问SSO进行验证,觉得这个步骤有点多余。他想SSO登录认证通过后,通过回调地址将用户信息返回给原业务系统,原业务系统直接设置登录状态,这样流程简单,也完成了登录,不是很好吗?

其实这样问题时很严重的,如果我在SSO没有登录,而是直接在浏览器中敲入回调的地址,并带上伪造的用户信息,是不是业务系统也认为登录了呢?这是很可怕的。

基于域的SSO

在基于域的SSO中,不同的应用程序都属于同一个父域名下的子域名。例如,应用程序A的域名可以是a.example.com应用程序B的域名可以是b.example.com。这些应用程序共享相同的用户身份验证机制和令牌。

当用户登录到其中一个应用程序时,身份验证会在父域名下进行。一旦用户成功登录,并在父域名下生成了令牌,该令牌可以被其他子域名下的应用程序共享和验证。这样,用户在访问其他子域名下的应用程序时,无需再次输入凭据,而是直接使用已验证的令牌进行登录。

一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:a.com,同时有两个业务系统分别为:app1.a.com和app2.a.com。我们要做单点登录(SSO),需要一个登录系统,叫做:sso.a.com

我们只要在sso.a.com登录,app1.a.com和app2.a.com就也登录了。通过上面的登陆认证机制,我们可以知道,在sso.a.com中登录了,其实是在sso.a.com的服务端的session中记录了登录状态,同时在浏览器端(Browser)的sso.a.com下写入了Cookie。那么我们怎么才能让app1.a.com和app2.a.com登录呢?这里有两个问题:

Cookie是不能跨域的,我们Cookie的domain属性是sso.a.com,在给app1.a.com和app2.a.com发送请求是带不上的。
sso、app1和app2是不同的应用,它们的session存在自己的应用内,是不共享的。
Alt text

那么我们如何解决这两个问题呢?针对第一个问题,sso登录以后,可以将Cookie的域设置为顶域,即.a.com,这样所有子域的系统都可以访问到顶域的Cookie。我们在设置Cookie时,只能设置顶域和自己的域,不能设置其他的域。比如:我们不能在自己的系统中给baidu.com的域设置Cookie。

Cookie的问题解决了,我们再来看看session的问题。我们在sso系统登录了,这时再访问app1,Cookie也带到了app1的服务端(Server),app1的服务端怎么找到这个Cookie对应的Session呢?这里就要把3个系统的Session共享,如图所示。共享Session的解决方案有很多,例如:Spring-Session。这样第2个问题也解决了。

同域下的单点登录就实现了,但这还不是真正的单点登录。

参考:https://developer.aliyun.com/article/636281
参考:http://www.taodudu.cc/news/show-4247685.html?action=onClick


评论