最近在研究SSO,看到各种复杂的解决方案觉得很疑惑,自己想出了个简单有效的方案,大家来评评有什么问题吗?
服务器A:网站A
服务器B:网站B
服务器C:验证网站(验证表中有UID和KEY两个字段)。
1. 用户打开网站A的页面http://服务器A/a.aspx,检测发现网站Session中没有存储用户名UID。
2. 系统转到验证服务器登录页面,并在QUERYSTRING中附加前一个页面的URL地址。比如http://服务器C/login.asp?URL=http://服务器A/a.aspx
3. 在验证服务器登录成功后更新验证服务器的Session(超时设置为足够长,比如1天)。然后生成一个GUID值,写入验证表。最后,把这个GUID值和UID保存到一个类中序列化后附加在URL中返回网站A的那个页面。比如http://服务器A/a.aspx? token=sadhsagdkjasgyugd7d8yweihasdiuhagsdiuashdhaiushdi
4. 网站A的页面读取QUERYSTRING,然后反序列化出一个类,读取类的UID和KEY信息。然后,从数据库中查找匹配的记录,如果找到了则表明登录成功,并把这条记录的KEY更新成另外一个GUID(这样就保证了即使这个URL被别人拿走再登录都不能成功)。把UID写入服务器A的Session中即可。
5. 用户打开网站B的页面http://服务器B/b.aspx,服务器B上没有当前用户的Session信息,自动转向验证服务器检测是否存在Session,如果找到了表明用户已经登录过,再重复步骤3和4,如果没有找到就转到验证服务器的登录页面。
巧妙之处在于:
l 网站服务器和验证服务器都拥有一份和用户关联的Session,验证到时候不需要传任何和UID相关的信息,因此也可以跨服务器。正因为如此不需要使用cookie也解决了跨域名。
l 网站服务器和验证服务器可以使用自己的状态机制(不一定是Session),因此跨平台也没有问题。
l 用于验证用户的TOKEN使用GUID在每次验证的时候都会更换,而且GUID和UID是捆绑在一起的,即使GUID碰巧对上了也不知道这个GUID对应了哪个UID。
l 通过验证服务器的验证后,服务器发回的token数据经过了序列化,用户很难伪造。
(实在不放心还可以对这个token进行加密)
不知道大家是否理解了?
我这个方案有什么重大缺陷码?
下载测试代码
更新:经过网友提醒,我想到这个方案在登出的时候有严重问题,比如A网站登出了,我们不能通知其它网站该用户已经登出,它再切换到其它网站又是登录状态(因为Session没有过期),不过我也想到了一个解决方案。就是登出的时候不仅把当前网站的Session进行Abandon而且也把登录服务器的Session Abandon,在每次切换站点的时候都去验证服务器验证是否Session有效。那么现在的问题就在于通过什么来判断用户是否切换了网站?虽然我们可以通过上一个页面的URL地址来判断,但它只适合跳转,打开新页面就不行了。大家是怎么做SSO的?要求是跨服务器跨网站的,比如像chinaren登录后sohu也能用。
或许还有一个办法就是所有的网站都有一个专门的页面或者服务,根据传过来的令牌来情况这个当前用户的Session。登出以后把所有网站的Session都清空,如果网站不是很多的情况下还好,网站一多登出就会很慢了!关键的问题还是在于如何同步验证服务器和各个服务器的状态。
同步讨论:http://community.csdn.net/Expert/topic/5070/5070325.xml?temp=.5259668