什么是SSO?
Web应用系统的演化总是从简单到复杂,从单功能到多功能模块再到多子系统方向发展。
当前的大中型Web互联网应用基本都是多系统组成的应用群,由多个web系统协同为用户提供服务。
多系统应用群,必然意味着各系统间既相对独立,又保持着某种联系。
独立,意味着给用户提供一个相对完整的功能服务,比如C2C商城,比如B2C商城。联系,意味着从用户角度看,不管企业提供的服务如何多样化、系列化,在用户看来,仍旧是一个整体,用户体验不能受到影响。
譬如用户的账号管理,用户应该有一个统一账号,不应该让用户在每个子系统分别注册、分别登录、再分别登出。系统的复杂性不应该让用户承担。
登录用户使用系统服务,可以看做是一次用户会话过程。在单Web应用中,用户登录、登录状态判断、用户登出等操作,已有很常规的解决方案实现。
在多系统应用群中,这个问题就变得有些复杂,以前本不是问题的问题,现在可能就变成了一个重大技术问题。我们要用技术手段,屏蔽系统底层本身的技术复杂性,给用户提供自然超爽的用户体验。
这就是我们所说的单点登录问题,即SSO(Single Sign On)。当然,我们这里主要讨论的是Web系统,确切地讲,应该叫Web SSO。
实际案例分析
下面我们来看一个现实中SSO的例子,例如阿里系统:
阿里目前给用户提供的服务很庞大,种类也很繁多,我们看几个典型系统应用:www.taobao.com 淘宝应用、www.tmall.com 天猫应用、
www.alitrip.com 阿里旅游。这些应用,当用户访问时,都需要登录
============================================
显然,对用户来说,他不希望每个子应用分别登录,因为这都是阿里服务,在用户看来,就相当于一个大系统。
当我在一个应用如淘宝上登录后,再访问阿里旅游、天猫等其它系统,我们发现,系统都显示已登录状态。
当在任意一系统退出登录后,再刷新访问其它系统,均已显示登出状态。
可以看出,阿里实现了SSO。实际上,几乎所有提供复杂服务的互联网公司,都实现了SSO,如阿里、百度、新浪、网易、腾讯、58...
SSO问题,是大中型Web应用经常碰到的问题,是Java架构师需要掌握的必备技能之一,中高级以上Web工程师都应对它有个了解。
SSO技术难点
SSO有啥技术难点?为什么我们不能像解决单Web应用系统登录那样自然解决?为说清楚这一问题,我们得先了解下单应用系统下,用户登录的解决方案。
我们讨论的应用是Web应用,大家知道,对于Web应用,系统是Browser/Server架构,Browser和Server之间的通信协议是HTTP协议。
HTTP是一个无状态协议。即对服务器来说,每次收到的浏览器HTTP请求都是单一独立的,服务器并不考虑两次HTTP请求是否来自同一会话,即HTTP协议是非连接会话状态协议。
对于Web应用登录,意味着登录成功后的后续访问,可以看做是登录用户和服务端的一次会话交互过程,直到用户登出结束会话。
如何在非连接会话协议之上,实现这种会话的管理? 我们需要额外的手段。
通常有两种做法,一种是通过使用HTTP请求参数传递,这种方式对应用侵入性较大,一般不使用。
另一种方式就是通过cookie。
cookie是HTTP提供的一种机制,cookie代表一小撮数据。服务端通过HTTP响应创建好cookie后,浏览器会接收下来,下次请求会自动携带上返回给服务端。
利用这个机制,我们可以实现应用层的登录会话状态管理。例如我们可以把登录状态信息保存在cookie中,这是客户端保存方式。
由于会话信息在客户端,需要维护其安全性、需要加密保存、携带量会变大,这样会影响http的处理效率,同时cookie的数据携带量也有一定的限制。
比较好的方式是服务端保存,cookie只保存会话信息的句柄。即在登录成功后,服务端可以创建一个唯一登录会话,并把会话标识ID通过cookie返回给浏览器,浏览器下次访问时会自动带上这个ID,服务端根据ID即可判断是此会话中的请求,从而判断出是该用户,这种操作直到登出销毁会话为止。
令人高兴的是,我们使用的Web应用服务器一般都会提供这种会话基础服务,如Tomcat的Session机制。也就是说,应用开发人员不必利用Cookie亲自代码实现会话的创建、维护和销毁等整个生命周期管理,这些内容服务器Session已经提供好了,我们只需正确使用即可。
当然,为了灵活性和效率,开发人员也可直接使用cookie实现自己的这种会话管理。
对于Cookie,处于安全性考虑,它有一个作用域问题,这个作用域由属性Domain和Path共同决定的。也就是说,如果浏览器发送的请求不在此Cookie的作用域范围内,请求是不会带上此Cookie的。
Path是访问路径,我们可以定义/根路径让其作用所有路径,Domain就不一样了。我们不能定义顶级域名如.com,让此Cookie对于所有的com网站都起作用,最大范围我们只能定义到二级域名如.taobao.com,而通常,企业的应用群可能包含有多个二级域名,如taobao.com、tmail.com、alitrip.com等等。
这时,解决单系统会话问题的Cookie机制不起作用了,多系统不能共享同一会话,这就是问题的所在!
当然,有的同学会说:我把所有的应用统一用三级域名来表示,如a.taobao.com、b.taobao.com、c.taobao.com或干脆用路径来区分不同的应用如www.taobao.com\a、www.taobao.com\b、www.taobao.com\c,这样cookie不就可以共享了么?
事实是成立的,但现实应用中,多域名策略是普遍存在的,也有商业角度的考虑,这些我们必须要面对。
退一步讲,即使cookie可以共享了,服务端如何识别处理这个会话?这时,我们是不能直接使用服务器所提供的Session机制的,Session是在单一应用范围内,共享Session需要特殊处理。
更复杂的情况是,通常这些子系统可能是异构的,session实现机制并不相同,如有的是Java系统,有的是PHP系统。共享Session对原系统入侵性很大。
至此,SSO技术问题这里讲清楚了。那我们有没有更好的通用解决方案?答案肯定是有的,但比较复杂,这也是我们专题讨论的理由。总体来说,我们需要一个中央认证服务器,来统一集中处理各子系统的登录请求。这是入门,后续会有系列文章深层次探讨。
对SSO技术,你应该至少了解以下内容:
-
大中型Web应用基本都是多系统组成的应用群,SSO是必须面对的基本问题。
-
Cookie有作用域限制,顶级域名Cookie不能共享,故登录会话不能共享。
-
直接改造各子系统共享Session,通用性灵活性不强,或对原系统入侵性大,不是解决SSO根本办法。
本文整理至:↓