实现多域单点登录SSO系统的步骤

实现多域单点登录SSO系统的步骤

多域单点登录SSO系统的实现


天幻网新的规划中,将涉及到多域,如FFSKY.COM,FFSKY.CN等等,因此网上某些对同一域靠设置COOKIE的DOMAIN=".FFSKY.COM"的方式根本行8通,因此考虑用纯粹的PASSPORT的机制。
建设此系统前,我做了充分的准备工作,参考了网上N多的SSO系统实现的文章,包括国内和国外的,发现SSO系统有许多都是商业版的,基于JAVA的有许多现成的开源项目,甚至有WEBLOGIC内置的。而基于.NET的最完善的似乎是MS的PASSPORT,但貌似用户信息全部要汇总到MS的PASSPORT网站,也就是说无法调用自己的用户数据库。另外还有现成的Discuz!论坛的PASSPORT,但只能用在两个站之间。还有一个基于.NET的SSO东东,但看了半天应该也是商业版的,要下载试用版还获取不要验证邮件- -b郁闷之下自己动手,丰衣足食~
自己所接触到的自有的SSO系统的网站其实有印象的就2个,一个是MOP,一个是CSDN,但似乎都是同一域下的。看N篇参考文章之后唯一让偶感觉到可以在天幻实行的就是通过统一认证网站认证后返回到源网站,在URL地址中加入返回参数,而源网站通过解析该参数获取用户认证信息。这种方式可以跨多域.
其基本流程是:用户登录某网站,点击“登录”,然后转向到认证服务器(PASSPORT),在认证服务器完成认证后携带加密后的参数转回到原网站,原网站解析加密信息后给予用户已经登录状态。
但是网上很多资料都没有说清楚几点,正如我前一篇开工前文章中所说的:
1、TICKET加密方式,DES还是RSA
2、用户注销操作怎么处理,在A域超时,消息肯定要给S验证域,那当时用户还在B域里玩也,到底算他注销不。
3、用户从A域转到B域,是否还要到S验证域验证一下。还是在用户登陆时就将信息发给各服务域。
4、按SAML协议标准,有一个环节居然是服务域和注册域交互验证。这和原先的SSO流程不符合,看来可能还需要开发一个WEBSERVICE来遵循这个协议。

而我设计的天幻的SSO流程中,对以上几点是这样处理的:
1、使用AES衍生的Rijndael处理,因为DES强度太差,而且只有密钥,而RSA虽然有公钥和私钥,但生成的数据长度实在太长,不利于在浏览器中携带。而Rijndael算法有一个密钥和一个IV向量,可以在其中做双重验证用。
2、注销操作没办法做到各域同步,忽略这一问题,由各域自己控制用户超时量
3、引入自动监测机制,每张需要验证用户的页面如果发现用户没有登录,自动到PASSPORT域转一圈作为验证,如果在PASSPORT域发现用户已登录,则设用户已登录状态。
4、由于采用Rijndael加密,为了最大化安全性,将IV作为服务主机和认证主机之间私密交换的信息,我采用的是WEBSERVICE方式。

明确了以上的要素,整个单点登录系统就相对明确了。懒得画图,直接文字叙述实现方式吧,也不贴代码了,因为代码没有优化过,比较难看,同时也为了保证安全性,呼呼

1、自动判断是否登录流程

某可能会判断用户是否登录的页面,如果发现用户用户未登录(我都是判断SESSION(“NAME”)是否为空),并且用户浏览器支持COOKIE(即支持会话),且SESSION(“AUTOLOGIN”)为NULL, 则先置用户SESSION(“AUTOLOGIN”)=“1”,然后自动将用户重定向到PASSPORT域进行鉴别,如果未登录,则直接返回,如果已登录,则重定向回的URL地址中加载认证字串。 为了防止用户每点一张页面都要到登录域验证,所以需要加载一个认证是否已验证过的SESSION,以及浏览器是否支持SESSION。
其中唯一的隐患在于ASP.NET碰到用户浏览器虽然支持COOKIE功能但用户手动关闭COOKIE的话无法判断。但相信这种情况不会太常见,而通常非注册用户访问页面张数也不会超过10张,所以即使存在此类问题对服务器压力也会比较校

2、子站点涉及的参数

我给每个子站点分配一个SITEID和一个密钥,他们是一一对应的。为什么要给每个子站点分配不同的?因为这样就能引入第三方开发的程序,而无需由第三方来读取网站数据库。同时也可以防止第三方程序密钥泄露造成可以模拟用户登录。
子站点在转到登录域的时候需要携带两个必要参数:SITEID和要转回的URL地址。SITEID用来让登录域判断要加密时使用的密钥(KEY),转回URL地址用以转回源地址用。

3、基本登录流程

在某子站点“登录”,转到登录域,登录域判断用户未登录(判断依据下述),要求用户输入必要信息(用户名/密码/是否记忆密码/验证码等),用户登录成功后写以下COOKIE信息:用户名、用户ID,用户IP、当前的SESSIONID、COOKIE有效时间(通常为几个小时)。然后用Rijndael算法,以当前的SESSIONID作为IV量,以对应该网站的KEY作为密钥,加密用户名、用户ID、IP、是否自动登录等等信息。同时,在数据库ONLINEUSER表中将登录信息插入数据库,保存登录人登录状态的SESSION,其实就是保存IV值。将加密后的字符串,连带用户的USERID作为TICKET参数返回给请求的网站,格式样本如下:
http://www.ffsky.cn/index.aspxticket=38_4bku80WzbgHpgk034Wy5pOc%2f4cpIRI%2fLDHKDqITstQM%3d
其中38即为我的用户名CHOCOBO在数据库的ID号。
而FFSKY.CN网站判断我在未登录状态,且QUERYSTRING有TICKET参数,则开始尝试解析TICKET参数。首先就是提取USERID和加密后字符串,然后调用PASSPORT认证网站中的一个WEB SERVICE,这个WEB SERVER传入USERID后即会从数据库中读取并返回用户最近的SESSIONID,即IV值。FFSKY.CN网站靠分配给它的密钥和通过WEB服务得到的IV值即获取了我的相关信息。
获取相关信息后还需要有一点,即防模拟URL登陆,这里用的方式是判断IP地址,即解析数据库中有登录时的IP,然后通过IP地址比对来判断用户是否状态有变。如果A登陆后B直接粘贴A的URL地址是无法正常登陆的. 但同一内网的人如果这样做会怎么样呢?猛一看貌似比较难解决,但这里就需要用到一个小技巧了,就是一些牛X哄哄的安全公司用的一次密码技术。我们在调用WEBSERVICE是否,在WEBSERVICE传会IV值后即将数据库中对应的IV值置空。也就是说这个KEY只能用一次,这样问题就迎刃而解了。

4、基本注销流程

注销流程其实应该分两个环节,子站注销和验证域注销。流程相当简单,先到子站的LOGINOUT。ASPX,在子站销毁SESSION,再重定向到验证域,在验证域销毁COOKIE中关键信息(USERID/当前SESSIONID等),在数据库中删除相关登录信息,再转回到原子网站。

5、自动登录

如前所述,用户访问某页面时自动会转到验证域判断是否登录过,而这时如果在验证域发现用户COOKIE中含有PASSWORD通过MD5加密过的信息,则会尝试自动登录机制。同时,如果用户在近期登录成功,即在COOKIE中有USERID信息,则尝试判断该COOKIE是否有效果,判断依据是看IP地址和COOKIE有效期,这里强置两点:1是IP地址必须和初始登录时一致,2是用户首次登录12小时后必须重新登录。如果一切PASS,则重新加密信息后转回请求页。

6、安全考虑

其实安全性主要有以下几方面攻击情况要考虑:
1)、暴力破密码:
在登录页加图片验证码,图片可以加强噪点等混淆机制,甚至可以将验证域用HTTPS方式。
2)、模拟COOKIE:
能获取某用户COOKIE信息有两类情况:掌握用户主机控制权,通过论坛等地方获取用户COOKIE部分参数内容(跨站攻击)。前者的话已无安全控制可言,而后者由于已经采用单一的域登录,理论上应该不可能通过跨站手法获取访问用户的COOKIE信息了。
3)、取得密钥模拟:
一是各子域密钥不同,二是采用Rijndael算法还有个IV量必须通过WEBSERVICE才能获龋两道锁应该比较安全了。
4)、模拟登陆URL地址
正如前面所述,通过一次密码的方式在WEBSERVICE中读取SESSIONID(即IV)后即将此值在数据库中去除。这样就可以防止第二方截取URL地址模拟登陆了。

结语:以上方式基本实现了天幻的SSO系统,其中还有很多小的编程细节和经验说也说8清楚,比如URL编码、取消自动登录、WEBSERVICE的IP验证……等等。此文仅描述流程部分,其中有许多是安全关注的焦点,编程部分还是看需要人的实力吧。这里就不做开源了,免得网站被无谓的攻击 ~O~ 发现以上流程有安全隐患漏洞的请留言,呼呼