该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-11-01
由于刚涉及sso不久,对他还不是很了解(不了解也敢写组件? 呵呵 见笑了) 所以问题再所难免,系统大家能够给予指正和帮助,先谢谢了. 下面贴一下简单的说明文档, 里面不牵涉技术细节,只是我对它的一个简单的描述 看看设计上有什么地方需要改进没 在过几天,根据大家对它的建议和意见 做些改善后 再把代码和详细的使用配制方法贴上来. (比较长 不好意思了) ========================================== 组件名称:S3O 一套轻量级的、简单易用的、高效的单点认证系统。 当然同样具有一定的安全性,也支持跨域。 S3O: Simple Single Sign-On ----> SSSOS 一个简简单单的单点认证组件, 既然 WWWC 叫做 W3C ,那自然SSSO也可以叫S3O了 ===================================== 系统特性: ===================================== 1 基于http协议 2 支持跨域认证 3 各个子应用采用自己的登录入口,并且拥有独立的授权模块 4 支持子应用间的同步 5 重要信息加密后,通过hessian传递,并使用一次性ticketKey,安全性可以得到一定的保障。 6 绝对轻量级 7 基本原理应该(因为我没读过CAS的源代码,只看过一些相关文章,所以不敢肯定)类似CAS的基本模式(而不是它的代理模式). ( 当然要比CAS简单while(true){很多}了。 ) 8 基于spring 和 hessian技术构建。缓存采用ehcache。 ===================================== 术语解释: ===================================== 子应用: 就是需要提供单点登录的各个应用。 认证中心: 单点登录的认证中心。它也是个web应用。 可以把它理解为一个存放用户名和密码的公共空间, 各个子应用可以从它这里取用户名和密码,然后调用各自的授权模块对用户进行授权。 在该单点登录系统中,认证中心并不提供授权服务。 认证中心在客户端的cookie: 用于存放ticket的cookie。各个子应用的cookie不能在跨域的子应用之间共享,所以需要认证中心的cookie存放数据。 ticket: 认证中心生成的一个具有唯一性的标识,作为键,用来在认证中心缓存中保存登录用户的信息 同时ticket还将存放在认证中心在浏览器端的 cookie内 ticketKey: 认证中心生成的一个具有唯一性的标识,作为键,用来在认证中心缓存中保存ticket。 它是一次性的,当以ticketKey为键,从认证中心缓存中读取一次ticket后,该键将失效。 ticketKey会通过http在子应用与认证中心之间传递。 service: 通常指的是hessian service。 通过开源组件hessian发布的一种类似web service的远程服务。 serverMethod: 也是一种发布的远程服务,但调用方法是通过url调用。 可以理解为类似struts的dispatch action的实现。 ( 就好像用下面的url访问dispatch action, 会自动执行action中的query方法一样 http://www.aaa.com/example.do?actionMethod=query ) 客户端浏览器、子应用、认证中心之间 就是通过各种service和serverMethod进行通讯的。 ===================================== 单点登录主要流程概述: ===================================== 判断用户是否已经登录: 当前子应用的session中有用户的基本信息,同时当前子应用的全局缓存中也有该用户的基本信息。 则认为该用户已经在当前系统中登录。两个条件缺一不可。 ================================================== 系统初始化流程: 1 启动认证中心(一个web应用)并进行相关的初始化(初始化filter、缓存、发布service等) 2 启动各个子应用(初始化filter、缓存、发布service等) 3 子应用通过hessian 向 认证中心 注册自己的信息(包括 子应用的url 子应用中发布的service等信息) 4 认证中心验证子应用是否有合法的key,没有合法的key,则不允许注册。 5 成功注册的子应用的信息会加入 认证中心的子应用信息列表内(一个全局缓存) 这个列表可以帮助认证中心向各个子应用来发广播,也可以用来在各个子应用间进行通讯和同步. ===================================== 登录流程 (假设登录A应用 登录的用户为 tom ) 1 通过A应用的登录页面输入用户名tom 以及 密码 2 调用A应用的授权模块进行授权,授权失败返回登录页面。 3 授权成功,则将用户名 密码(加密后)通过hessian 发往 认证中心。 4 认证中心对其进行缓存,并产生ticket,将ticket和用户基本信息放入认证中心的缓存 5 同时还将生成ticketKey,以ticketKey做为键,把ticket放入认证中心端的一个临时的缓存内。 6 将ticketKey通过hessian返回给A应用。 7 A应用得到ticketKey后,通过内部redirect访问认证中心的指定url,该url用于产生cookiet (该cookie为认证中心在客户端产生,cookiet内存放ticket)。 8 完成写cookie操作后 ,清楚临时缓存中的ticketKey和ticket。 9 以上步骤成功完成后,将在A应用session和全局缓存中放置用户的基本信息(用户名 ticket)。 此时,对于a应用来说,用户tom的状态为已登录. ===================================== 登出流程 (假设登出A应用,登出的用户为 tom ) 点击登出按钮,或进行重新登录的时候,会对先前登录时产生的信息进行销毁。 1 清空A应用的session和全局缓存中放置的tom的基本信息 2 向认证中心发出tom登出的通知。 3 认证中心接收到通知后,会把该通知通过hessian广播给所有子应用(利用子应用启动时向认证中心注册的信息来实现广播)。 4 接到通知的各个子应用会清空应用的全局缓存中放置的tom的基本信息。 因为“已经登录”的前提条件是 session中和应用的全局缓存中也有该用户的基本信息, 所以这时,在所有的子应用中,tom的状态都是为登出,这样做到了各个子应用间的同步。 对于登出的处理,和cas完全不同,cas是通过消灭cookie. ===================================== 访问流程: (登录后,在各个子应用间切换的流程比较复杂,所以最后讲.) 假设tom已经通过A应用的入口 成功登录了A应用,并且认证中心正常工作。 此时访问B应用 1 判断tom是否已经登录了B应用 (通过判断B应用的session和全局缓存中是否有该用户的基本信息) 2 如果有 说明已经登录过(访问过)B应用,则进行正常访问。 3 如果没有,即tom没有登录过B应用,则尝试去认证中心 取用户的相关信息。 过程如下: 4 redirect到认证中心的指定url(同时发送当前用户请求的地址给认证中心),并从cookie中取ticket。 (cookie不能跨域,不redirect到认证中心是取不到ticket的)。 5 如果没有取到合法的ticket,则通知B应用跳转到登录页面(或出错页面)。 6 如果取到了ticket 则生成一个一次性的ticketKey,把ticket放入一个临时缓存,并返回B应用,同时把ticketKey返回给客户端。 7 B应用根据ticketKey从认证中心取用户名 密码. 过程如下:通过hessian 把 ticketKey 传递给认证中心,认证中心根据ticketKey去取ticket。 如果取到合法的ticket,则根据 ticket 通过hessian ,从认证中心的全局缓存中取得加密的 用户名 密码。 8 完成以上操作后 ,清除临时缓存中的ticketKey和ticket。 9 使用取得的用户名 密码,调用B应用的授权模块进行授权... 过程类似登录过程,但不需要认证中心重新产生ticket。 10 授权成功则 在B应用的session和全局缓存中放置用户基本信息,然后进行正常访问。 11 授权失败返回登录页面,并通知认证中心注销该ticket和用户基本信息(可以理解为,那个ticket失效了), 注销ticket时,认证中心会根据认证中心端的子应用列表,来通知各个子应用这个ticket失效了 各个子应用会从自己的全局缓存中清楚该ticket和其对应的用户基本信息(如果存在的话),过程类似登出过程。 ===================================== 关于安全问题的一些探讨: 在这个系统中最需要保护的是用户名 密码 和 ticket。由于ticketKey具有瞬时性,被盗用的意义不大。 用户名 密码 和 ticket 始终通过 hessian传递,并且加密,即使被拦截,被盗用和破解的几率也极低. ticketKey大多数情况下是通过hessian传递,但某应用第一次去认证中心取ticketKey时, ticketKey是通过http的url传送的(这是不能避免的,即使强大的cas也是使用的这种方式,不同的是他使用了https, 其实,此处也是CAS坚持要使用HTTPS的一个主要原因) 减少"通过http协议,由URL传递ticket"的弊端的方式有三种: 1 使用HTTPS 2 使用一次性ticketKey 3 给ticketKey提供较短的失效时间 在这里我使用了 第2种方法。基本上可以避免ticketKey被盗用。 也许有人会想,如果可以生成一个和浏览器所在机器或用户IP绑定的ticketKey是不是可以解决这个问题, 即ticketKey被盗后,如果在其他机器使用,则无效。 这种思路看起来似乎可以,但其实不然。 原因很简单,web应用不能清晰准确的识别哪些访问来自同一台机器,从而可能导致合法的用户也无法对系统进行正常的访问。 http vs. https 单点登录系统中 保护用户名 密码 用户信息的唯一标识(ticket)是首要任务。 而坏人(在这里先这么称呼吧 因为我真的不想玷污黑客这个词)最想得到的就是这三者。 为了防止用户名 密码 ticket被盗,于是大多数sso系统采用了https。 在此处 https 比 http最主要最明显的优势就是传输的数据经过加密。 使得数据封包被拦截后,也几乎不可能从中破解出传输的数据。 但是,现在的坏人,主要的窃取用户信息的手段是什么? 在网内拦截封包,然后自己破解??错了,是用最简单的木马程序。 侵入用户的机器,直接记录键盘、拦截页面表单提交.... 如果一个坏人,有能力侵入网络,来拦截各个机器之间的数据封包和http请求,那么他肯定也有能力直接在客户端的机器里做些手脚。 说的可能有些凌乱,重新总结一下吧: 如果想拥有可靠的安全性,要具备下面的几点: 1 整个网络系统 有完善的防火墙(使坏人不能随意的拦截网络数据封包) 2 认证中心、子应用所在机器要拥有完善的防火墙、完善的杀毒、防毒软件。 3 客户浏览器所在机器上,要有完善的防火墙、完善的杀毒、防毒软件。(这点最难保证) 4 机器之间的数据传输使用安全的传输协议(例如https) 以上4条,如果前3条得不到保证,那么安全性就无从谈起,第4条也就无足轻重了。 而如果前3条都满足了,那么第4条即使不满足,整个系统也同样安全,第4条同样无足轻重。 只有在 第2 3 条都满足,且第1条不满足的情况下,https才有用武之地。 所以,我的观点就是,对于"非公网"的单点认证系统,https不是必须的。 它在安全性方面起到的作用,和它带来的弊端想比,往往是弊大与利。 (其实,单点登录的系统,几乎都是企业内部的、非公网的系统) 注意:以上所言,都是针对传输的数据是 登录用户名 登录用户名 和 ticket的情况,如果传输是其他数据,则另当别论。 ===================================== 目前已知不足: 1 不支持https协议。(虽然不是必须的,但毕竟很多时候还是需要用到https的,所以暂且算做一个不足吧) 2 不支持"同一用户在不同子应用中使用不同口令"的情况。 3 不支持同一台计算机上用多个账号同时登录。 4 和acegi结合的接口程序还没有编写完毕。 5 没有经历过绝对严格的测试。 6 整个系统完全没有任何的日志功能(我认为目前这不是必须的,而且我还不会用log4j common-logging这类组件) 7 认证中心端的管理模块还没有编写(同样,我认为目前这也不是必须的,完善基本功能是首要任务) 8 不支持类似CAS的业务代理模式。 9 不支持认证中心端的授权(本sso组件在设计的时候就没打算实现这个功能,呵呵) 10 虽然hessian支持多种语言,但是本sso组件没有提供非java的客户端版本。 ===================================== 下一步工作: 1 完成与acegi的接口编码。 2 将 加密模块、唯一标识生成模块从主体中分离出来,可以通过配置来实现不同的加密、生成算法(类似acegi的做法)。 3 将 用户信息模型从主体中分离出来,做到更好的解藕,可以根据不同的需要配置不同的用户信息模型。(但核心仍然是Map来装载数据) 4 做一个稍微好点的S3OClient,但不会太好,因为计划将acegi作为client的主要承载者 5 提供从认证中心处统一登录(也就是提供统一的登录入口)。 6 支持认证中心端的统一授权。 7 认证中心端的简单的管理程序(查看认证中心中各种缓存中的数据) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-11-02
昨天本来想把 和 acegi的接口写完了
就把代码和例子发上来 可是由于以前懒惰 没有看过acegi 现看已经晚了 所以我决定还是不等了 晚上就先发上来吧 我爱写程序 但是不爱写注释 更不爱写文档 郁闷啊 所以发的还是代码和例子 发了在下面: http://www.iteye.com/topic/32235 |
|
返回顶楼 | |
发表时间:2006-11-03
用CAS就好了, 我的项目里就是用的CAS
不去学习别人, 自己闭门造车, 所以中国人一盘散沙 |
|
返回顶楼 | |
发表时间:2006-11-03
(其实,单点登录的系统,几乎都是企业内部的、非公网的系统)
-------- 对这句话还是有异议的,外网上类似于通行证等实现其实就是单点登陆的,单点登陆应用很广的。 |
|
返回顶楼 | |
发表时间:2006-11-03
plato 写道 用CAS就好了, 我的项目里就是用的CAS
不去学习别人, 自己闭门造车, 所以中国人一盘散沙 通过这么个小习作似的东西,就把问题上升到“中国人一盘散沙”的高度了? 这有点... 而且我也没说不学习啊 我已经开始看cas的代码了 我学习的过程一般是这样: 先学思想 然后自己动手做个简陋版本的 然后再看人家的 从中对比出差距来 (当然指的是一些小东西 太复杂的一我不感兴趣 二我没那能力 ) 就像小时候做作业 肯定是先做完了 再去对答案的 总不能把答案拿来就用吧 |
|
返回顶楼 | |
发表时间:2006-11-03
noble 写道 (其实,单点登录的系统,几乎都是企业内部的、非公网的系统)
-------- 对这句话还是有异议的,外网上类似于通行证等实现其实就是单点登陆的,单点登陆应用很广的。 但那种登陆一般都不是真正跨域的 都做了域名映射 例如 mail.sina.com blog.sina.com sports.sina.com ... 公网的 真正的跨域单点登录还是很少见的 不跨域用cookie就ok了 我觉得不能算做严格意义上的单点登陆 |
|
返回顶楼 | |
发表时间:2006-11-03
跨域的 ms的passport算一个
其他还真没见到什么。 不过不清楚退出时候 这个是怎么通知其他的也退出的。 查看,是存了cookies的。 |
|
返回顶楼 | |
发表时间:2006-11-03
叶子 写道 跨域的 ms的passport算一个
其他还真没见到什么。 不过不清楚退出时候 这个是怎么通知其他的也退出的。 查看,是存了cookies的。 各个子应用在启动的时候 向 认证中心注册了自己的信息 当用户退出的时候 把退出的消息发送给认证中心 认证中心利用自己得到的子应用的信息,向所有子应用发出 某某某 退出的消息 (实际上是调用 子应用发布的 hessian service) 这样各个子应用就也都知道 某某某退出了 不知道说明白没 |
|
返回顶楼 | |
发表时间:2006-11-04
fins 写道 叶子 写道 跨域的 ms的passport算一个
其他还真没见到什么。 不过不清楚退出时候 这个是怎么通知其他的也退出的。 查看,是存了cookies的。 各个子应用在启动的时候 向 认证中心注册了自己的信息 当用户退出的时候 把退出的消息发送给认证中心 认证中心利用自己得到的子应用的信息,向所有子应用发出 某某某 退出的消息 (实际上是调用 子应用发布的 hessian service) 这样各个子应用就也都知道 某某某退出了 不知道说明白没 这种情况怎么处理? |
|
返回顶楼 | |
发表时间:2006-11-04
china2wto 写道 fins 写道 叶子 写道 跨域的 ms的passport算一个
其他还真没见到什么。 不过不清楚退出时候 这个是怎么通知其他的也退出的。 查看,是存了cookies的。 各个子应用在启动的时候 向 认证中心注册了自己的信息 当用户退出的时候 把退出的消息发送给认证中心 认证中心利用自己得到的子应用的信息,向所有子应用发出 某某某 退出的消息 (实际上是调用 子应用发布的 hessian service) 这样各个子应用就也都知道 某某某退出了 不知道说明白没 这种情况怎么处理? 我说的是ms的处理方法 你的看我看懂了 另to:楼上,个人感觉应该有超时机制的。 各个子应用和认证中心也要定时清理(死机,掉线,没有操作)的用户,执行退出操作。 |
|
返回顶楼 | |