SSO全称Single Sign On,单点登录.用于实现多系统的登录认证.说白了就是只要一个账号就可以访问阿里旗下支付宝,淘宝, 天猫等网站.站在企业的角度这样做有一个好处:只要有一个系统负责登录模块,其他的子系统就可以专注于自己系统的业务逻辑,需要的时候请求认证系统就可以.站在用户的角度好处在于只要一个账号就可以访问其公司旗下所有产品.
SSO有多种实现方案,这次我们来分析一下其中的一种可行方案.并且撸起袖子代码实现一遍.其实现效果如下
一个账号可以同时访问www.a.com跟www.b.com
账号在一个系统中退出,其他系统也同样退出.
如果需要,改动一点代码可以实现账号在www.a.com登录之后访问www.b.com不用进行账户密码登录认证.
原理
在实现之前,我们来分析一下整个流程.
通常情况下,系统判断用户是否登录都是校验session.在SSO架构中,判断用户是否登录仍然依靠session,但是session由SSO server维护, session_id由client保持,client直接访问的却是业务系统.
在这样的情况下,要想能够使用session进行登录验证. 假设client访问业务系统,业务系统取得其session_id,然后把session_id提交到SSO Server进行验证.我们看到这里的业务系统充当了一个proxy的角色,下文以proxy指代各个业务系统.
这种方式简单粗暴,但是有一个很大的局限性 : client持有的session_id由SSO Server发布的,proxy跟SSO Server必须持有相同域名,不然proxy无法获取到client的session_id.所以需要在这种思路上做一点改变.
client访问proxy,proxy随机生成一个token作为cookie保存,并且SSO Server维护有一个以token为文件名的文件,文件保存了client访问SSO Server生成的session id.当proxy需要验证client身份,只要获取到token,到SSO Server访问token文件,获取到session id.那么久可以访问到session数据.从而判断该client是否已经登录.
总体设计思路如上,但是除了token,为了保证安全性,以及多个proxy之间不会产生冲突.一个完整的流程应该如下 :
-
client ---> proxyA.proxyA为client生成一个随机的token当做cookie.然后引导client重定向到SSO Server.其中引导client重定向到SSO Server应该包含如下信息
token,由proxy生成的随机值
command 即访问SSO Server的目的,一般为SSO Server系统中的一个函数名.
returnUrl : 一般为client访问proxyA的url,即SSO Server 会重新引导client返回当前页面
当前proxy的ID.proxy跟SSO Server之间约定好的一个唯一ID,并且每个唯一ID必须对应一个secret key.这个key只有当前proxy跟SSO Server知道.
checksum : 一个包含上述信息和secret key的单项加密,用于SSO Server验证参数是否被恶意修改.
上述的重定向url应该类似
www.sso.com?token=xxx&command=xxx&returnurl=xxx&proxy=proxyA&checksum=xxx
.client被proxyA重定向到SSO Server之后,SSO校验参数的合法性后为client生成一个session_id.并且创建一个以proxyID-token-checksum的命名的文件,保存当前client的session id.完成上述操作之后引导client重定向到returnUrl.这样用户的体验不会受到影响.client重定向到proxyA后可以进行登录操作,proxyA可以从cookie中获取到token.client提交用户名跟密码,proxyA重新生成一个proxyID-token-checksum的字符串,然后和用户名密码一起提交到SSO Server.
SSO Server收到proxyA的请求之后校验请求的合法性,然后获取到proxyID-token-checksum文件中的session_id.在验证用户密码之后把登录信息以proxyID--->username的形式写到session中.之后返回用户信息给proxyA.
proxyA受到SSO Server的用户信息之后,判断登录成功.
当用户在多个proxy上登录,就会在sesion中维护多个proxyID--->username的键值对信息.用户从一个系统退出,proxy代理client向SSO Server发起退出请求.SSO Server按照上面的步骤获取到session id.删除掉所有的session数据.这样其他proxy的登录信息也被删除.下次访问需重新登录.
实现
上面的流程都清楚了,下面来尝试用代码实现
首先必然得有两个模块,proxy跟SSO Server.为了能在机子上运行处效果,需要配置虚拟主机,如果想提前看到效果, 可以在这里的SSO目录下找到全部源码,在apache下配置好www.a.com, www.b.com以及www.sso.com三个网站,并且在/etc/hosts下配置www.sso.com的ip地址.然后把SSO目录下的三个子文件夹分别放到对应目录下.
整个系统中,proxy在三种情况下会请求SSO
attach.主要是为了通过client携带token给SSO.并且SSO 分配session_id 给client
login ,登录.proxy代理 client向SSO发起身份验证的请求.
logout, 退出登录,清除SSO维护的session数据.
好了,整个SSO的分析就到这里了,源码在github可以找到, 而且, 如果懂得上面的认证流程,看懂代码是很简单的事情.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。