




已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
使用CAS做为SSO的性能问题讨论。 最近有个项目使用了开源的CAS做为SSO,看了一些资料之后觉得它某些方面还是相当优秀的。 它的实现原理是这样的: 假设用户在访问/tp之前需要验证身份,我们把用户从/tp重定向到下面的Login URL: /cas/servlet/login?service=/tp/authenticate.jsp JSP页面authenticate.jsp是网站资源的一部分。一旦完成了上面描述的初步身份验证,CAS用下面的URL重定向用户浏览器到这个JSP页面: /tp/authenticate.jsp?ticket=opaque-ticket-string 一旦收到请求,authenticate.jsp页面需要校验这个收到的ticket,它把tickect传送Validation URL(如/cas/servlet/validate)。authenticate.jsp页面需要使用JSSE向Validation URL发送请求并读取数据。当生成这个请求时,authenticate.jsp页面还需要把先前的service ID用service的参数名传送给Validation URL,例子如下: /cas/servlet/validate?ticket=T&service=S 当CAS从Validation URL收到这个ticket,它检查自己内部数据库,看看是否保存过这个ticket。如果数据库有这个ticket,则进一步检查数据库中和ticket关联的service是否和刚收到的service相匹配。如果匹配,则向请求验证身份的应用URL返回NetID;否则拒绝验证这个请求。 在当在线用户达到几千万级时,这样的反反复复的redirect(就是无数次的http请求与应答)还有它的内部数据库,是否存在严重的性能问题? 原创S3O:一个简单的单点认证系统(一) 最近写了一个简单的单点认证系统(更喜欢称它为组件) 由于刚涉及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方法一样 /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 认证中心端的简单的管理程序(查看认证中心中各种缓存中的数据) 这回把粗糙的代码 和示例发上来了,并简单说一下部署这个示例的方法 (没有传依赖的jar包, commons-codec-1.3.jar 46,725 commons-logging-1.0.4.jar 38,015 ehcache-1.2.3.jar 208,048 hessian-3.0.20.jar 235,464 spring.jar 2,545,110 ) 这个sso组件 由于比较小巧 所以没有把 server 和 client分离 部署子认证中心(server端) 附件中的示例默认配置是 server端的 你可以把他部署为任意的应用名字 例如 部署到 http:/IP1:8080/s3otest 其他的都不需要修改。 部署子应用(client端) 同样的代码 用WebContentWEB-INFclient.config下的文件 替换 WebContentWEB-INF下的文件 然后再部署为任意的名字 例如 部署成 http:/IP2:8080/s3oclient1 再然后去修改 WEB-INF下的S3OClientContext.xml, 根据实际情况修改下面内容 修改为 然后就ok了。 依次类推 再部署若干个子应用(client端) 如http:/IP2:8080/s3oclient2 ,http:/IP2:8080/s3oclient3. 记得修改相应的S3OClientContext.xml文件。 然后启动这些应用就可以了 然后可以从任意一个子应用登陆 例如 http:/IP2:8080/s3oclient1 由于是首次访问,系统自动跳转到 登录页面 我提供的默认的验证模块很简单 只要 你的用户名和密码一样 并且长度大于等于3 就可以登陆 登陆后 你可以尝试着去访问其他的应用的页面 (需要修改一下 示例jsp文件中提供的连接 或者手动打另外一个应用的url) sso研究2-跨域cookie 用跨域cookie实现sso 是比较简单的 主要用两个操作:登陆和登出登陆操作 - SSOLoginServlet来实现用户输入用户名密码Sso server验证其正确性将用户名加密后写入cookieCookie cookie = new Cookie(SSOConst.SSOID_KEY, ssoid);cookie.setMaxAge(maxAge); cookie.setDomain(.);cookie.setPath(/);以上几行代码是sso的核心cookie.setDomain(.);这句代码可以实现所有的以.结尾的域名都能访问这个cookie登陆操作完成 此时这个标志用户已经登陆的cookie 被写进了浏览器的cookie登出操作 - SSOLogoutServlet来实现客户端只要调用这个servlet就完成了用户的登出这个servlet完成的操作就是把登陆时写的cookie 删除掉我们只需要将这个cookie的maxAge 设置为0即可子域之间的交互 假设有两个应用A. 和 B.如果我在a应用中登陆成功 那么当我切换到B的时候 B怎么能感知到用户已经登陆呢?过滤器可以很好的解决这个问题 - SSOFilter假如我在A中成功登陆,现在要访问B,那么可以在访问b的受保护页面的时候先经过过滤器,过滤器的功能是检查是否存在这个cookie,如果存在表示用户已经登陆,否则转到登陆页面Yale CAS最佳实践 -全部 Yale CAS最佳实践 第一部分:配置篇 1.环境准备 Jdk1.4.2 Tomcat5.0.28 cas-server-2.0.12(没有采用更高版本,是因为它最简单明了) cas-client-java-2.1.1 2.在jdk上配置SSL 到/products/jsse/去下载jsse,我用的是1.0.3;下载下来后是一个zip包,把里边lib目录下的jar包复制到你的jdk目录下的jrelibext目录中,是三个文件:jsse.jar;jnet.jar;jcert.jar 3.SSL验证证书 3.1.生成 keytool -genkey -alias tomcat -keyalg RSA ? 如果C:Documents and SettingsAdministrator.keystore已经存在,请先删除。 ? 输入tomcat本身的缺省口令changeit ? 用户前名和用户后名都用localhost keytool -export -alias tomcat -file server.crt 只能输入tomcat的缺省口令changeit keytool -import -trustcacerts -alias tomcat -file server.crt -keystore %java_home%/jre/lib/security/cacerts 3.2.显示 keytool -list -v -keystore %java_home%/jre/lib/security/cacerts t.txt 3.3.删除 keytool -delete -alias tomcat -keystore %java_home%/jre/lib/security/cacerts -keypass changeit 只能输入tomcat的缺省口令changeit 3.4.keytool参考 %JAVA_HOME%binkeytool -delete -alias tomcat -keypass changeit %JAVA_HOME%binkeytool -genkey -alias tomcat -keypass changeit -keyalg RSA %JAVA_HOME%binkeytool -export -alias tomcat -keypass changeit -file %FILE_NAME% %JAVA_HOME%binkeytool -import -file server.crt -keypass changeit -keystore %JAVA_HOME%/jre/lib/security/cacerts %JAVA_HOME%binkeytool -import -file server.crt -keypass changeit %JAVA_HOME%binkeytool -genkey -alias tomcat -keypass changeit -keyalg RSA -validity 365 4.Tomcat配置 4.1.拷贝 拷贝C:Documents and SettingsAdministrator.keystore到tomcat_home%conf 4.2.配置 编辑tomcat_home%confserver.xml,去掉ssl的注释,并更改为如下配置 4.3.注意 请保持C:Documents and SettingsAdministrator.keystore与tomcat_home%conf.keystore一致 5.Tomcat jmx bug 在sun网站上/javase/technologies/core/mntr-mgmt/javamanagement/download.jsp 下载jmx-1_2_1-ri.zip,解压后,把jmxri.jar重命名为jmx.jar,覆盖tomcat/bin目录下的jmx.jar 这个适用于cas-server-3.* Yale CAS最佳实践 第二部分:原理篇 6.概念术语 CAS(Central Authentication Service) TGT(Ticket Granting Ticket) ST(Service Ticket) PGT(Proxy Granting Ticket) 7.原理剖析 Yale CAS使用了Ticket Granting Cookie (简称TGC)去作为获取Service Ticket(简称ST)的凭据,这个TGC 是保存在客户端的cookie,即当第2次被其他CAS Client重定向的时候,CAS Server实际上已经从用户的Cookie中抓取到TGC,然后知道TGC对应的用户,因此避免了再次登录,如果CAS Server抓取不到TGC,则用户需要登陆。 众所周知,cookie是不能跨域的。但是CAS能够做和的sso,因为CAS Server缓存了所有的ticket,所以Client无需共享cookies。 Yale CAS最佳实践 第三部分:源代码研读 8.源代码研读 8.1.web.xml参数定义: edu.yale.its.tp.cas.client.filter.loginUrl: CAS server的login URL. (Required) edu.yale.its.tp.cas.client.filter.validateUrl: CAS server的URL验证器. (Required) edu.yale.its.tp.cas.client.filter.serviceUrl: URL of this service. (Required if serverName is not specified) edu.yale.its.tp.cas.client.filter.serverName: 主机名:端口号 edu.yale.its.tp.cas.client.filter.authorizedProxy: 身份验证代理,用空格隔开.必须有一个. (缺省,只接受ST,不接受PT) xyCallbackUrl: 本地代理回调监听器,用来接受PGT/PGTIOU. (可选) edu.yale.its.tp.cas.client.filter.renew: 是否重新登录参数(缺省为false) edu.yale.its.tp.cas.client.filter.gateway: 是否使用网关.虽然英文不难明白,但的确不懂到底有什么用,因而不敢断章取义,望哪位高手能补充一下,在此谢过 edu.yale.its.tp.cas.client.filter.wrapRequest: 封装了HttpServletRequest,重载了getRemoteUser()方法. 如果设置为true, request.getRemoteUser()将返回登录用户名.(可选的,缺省为false.) 8.2.总体结构图 8.3.client源代码研读 8.4.server源代码研读 Yale CAS最佳实践 第四部分:试试身手 1.测试类 我写了一个RequestInfoServlet,可以显示HttpRequest的绝大部分有用信息,经过sso后,可以查看 HttpRequest里面还有什么东西。呵呵,我喜欢这样干。 Java代码 1. importjava.io.IOException; 2. importjava.io.PrintWriter; 3. importjava.util.Enumeration; 4. 5. importjavax.servlet.ServletException; 6. importjavax.servlet.http.Cookie; 7. importjavax.servlet.http.HttpServlet; 8. importjavax.servlet.http.HttpServletRequest; 9. importjavax.servlet.http.HttpServletResponse; 10. importjavax.servlet.http.HttpSession; 11. 12. /* 13. *authorLiujjDate2006-12-19 14. *Description: 15. *RequestHeadersServlet 16. */17. publicclassRequestInfoServletextendsHttpServlet 18. publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) 19. throwsIOException,ServletException 20. response.setContentType(text/html); 21. PrintWriterout=response.getWriter(); 22. /header 23. EnumerationheaderNames=request.getHeaderNames(); 24. out.println(*1.beginprintheaderNames*); 25. while(headerNames.hasMoreElements() 26. Stringname=(String)headerNames.nextElement(); 27. Stringvalue=request.getHeader(name); 28. out.println(name+=+value+); 29. 30. out.println(*1.endprintheaderNames*); 31. 32. /attributeNames 33. out.println(*2.beginprintattrib
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 低碳生活理念商品房买卖合同预售推广协议
- 新媒体运营策划方案实操指南
- 环境噪声与振动监测员节假日后复工安全考核试卷含答案
- 后勤管理员节假日后复工安全考核试卷含答案
- 刨花制备工节假日后复工安全考核试卷含答案
- 园林绿化养护管理日志模板
- 机舱拆解工节假日后复工安全考核试卷含答案
- 2025年农业合作社养殖合同书
- 花卉园艺工节假日后复工安全考核试卷含答案
- 实木及实木复合地板备料工节假日后复工安全考核试卷含答案
- 2024年安徽省泾县人民医院公开招聘护理工作人员试题带答案详解
- 2025年小学英语教材培训心得体会范文
- 2025年广西继续教育公需科目考试试题和答案
- 系统性风险压力测试框架-洞察阐释
- 数据迁移及备份服务合同
- 子宫动脉栓塞术后护理常规
- 教育中的数字化转型读书心得体会
- 幼儿园一日工作流程解读
- 纤支镜灌洗的术前术后护理讲课件
- 加气站风控分级管理制度
- 乡墅建房公司运营管理制度
评论
0/150
提交评论