SSO CAS原理浅谈

来源:互联网 发布:ucl data science 知乎 编辑:程序博客网 时间:2024/05/17 03:38

1. CAS简介

   SSO是一个非常大的主题,我对这个主题有着深深的感受,自从广州UserGroup的论坛成立以来,无数网友都在尝试使用开源的CASKerberos也提供另外一种方式的SSO,即基于Windows域的SSO,还有就是从2005年开始一直兴旺不衰的SAML

   如果将这些免费的SSO解决方案与商业的TivoliSiteminderRSA Secure SSO产品做对比,差距是存在的。毕竟,商业产品的安全性和用户体验都是无与伦比的,我们现在提到的SSO,仅仅是Web SSO,即Web-SSO是体现在客户端;另外一种SSO是桌面SSO,例如,只需要作为Administrator登录一次windows 2000,我便能够在使用MSN/QQ的时候免去登录的环节(注意,这不是用客户端软件的密码记忆功能),是一种代理用户输入密码的功能。因此,桌面SSO是体现在OS级别上。

   CAS(CentralAuthenticationService)是Yale大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的单点登录解决方法(属于WebSSO)。

   CAS开始于2001年,并在2004年12月正式成为JA-SIG的一个项目。

   今天,当我们提起SSO的时候,我们通常是指Web SSO,它的主要特点是,SSO应用之间走Web协议(HTTP/SSL),并且SSO都只有一个登录入口。

   主要特性:

   1. 开源的、多协议的SSO解决方案;Protocols:CustomProtocol、CAS、OAuth、OpenID、RESTfulAPI、SAML1.1、SAML2.0等
   2. 支持多种认证机制:ActiveDirectory、JAAS、JDBC、LDAP、X.509Certificates等;
   3. 安全策略:使用票据(Ticket)来实现支持的认证协议;
   4. 支持授权:可以决定哪些服务可以请求和验证服务票据(ServiceTicket);
   5. 提供高可用性:通过把认证过的状态数据存储在TicketRegistry组件中,这些组件有很多支持分布式环境的实现,如:BerkleyDB、Default、EhcacheTicketRegistry、JDBCTicketRegistry、JBOSSTreeCache、JpaTicketRegistry、MemcacheTicketRegistry等;
   6. 支持多种客户端:Java、.Net、PHP、Perl、Apache,uPortal等。

  

   简单的SSO的体系中,会有下面三种角色:

   1User(多个)

   2Web应用(多个)

   3SSO认证中心(1个)

  虽然 SSO 实现模式千奇百怪,但万变不离其宗:

   1Web应用不处理User的登录,否则就是多点登陆了,所有的登录都在SSO认证中心进行。

   2SSO认证中心通过一些方法来告诉Web应用当前访问用户究竟是不是张三/李四。

   3SSO认证中心和所有的Web应用建立一种信任关系,SSO认证中心对用户身份正确性的判断会通过某种方法告之Web应用,而且判断结果必须被Web应用信任。

2. CAS的基本原理

   CAS(Central Authentication Service)Yale大学发起的一个开源项目,据统计,大概每10个采用开源构建Web SSOJava项目,就有8个使用CAS。对这些统计,我虽然不以为然,但有一点可以肯定的是,CAS是我认为最简单实效,而且足够安全的SSO选择。

  本节主要分析CAS的安全性,以及为什么CAS被这样设计,带着少许密码学的基础知识,我希望有助于读者对CAS的协议有更深层次的理解。

2.1 CAS的结构体系

从结构体系看,CAS包含两部分:

l         CAS Server

CAS Server负责完成对用户的认证工作,CAS Server 需要独立部署,有不止一种CAS Server的实现,Yale CAS ServerESUP CAS Server都是很不错的选择。

CAS Server会处理用户名/密码等凭证 (Credentials) ,它可能会到数据库检索一条用户帐号信息,也可能在 XML 文件中检索用户密码,对这种方式,CAS 均提供一种灵活但同一的接口/实现分离的方式,CAS究竟是用何种认证方式,跟 CAS 协议是分离的,也就是,这个认证的实现细节可以自己定制和扩展。

l         CAS Client

   CAS Client 负责部署在客户端(注意,我是指Web应用),原则上,CAS Client的部署意味着,当有对本地 Web 应用的受保护资源的访问请求,并且需要对请求方进行身份认证,Web应用不再接受任何的用户名密码等类似的Credentials ,而是重定向到CAS Server进行认证。

   目前,CAS Client支持(某些在完善中)非常多的客户端,包括Java.NetISAPIPhpPerluPortalAcegiRubyVBScript 等客户端,几乎可以这样说,CAS协议能够适合任何语言编写的客户端应用。

2.2 CAS协议

  剖析协议就像剖析设计模式,有些时候,协议让人摸不着头脑。CAS的代理模式要相对复杂一些,它引入了一些新的概念,我希望能够在这里描述一下其原理,有助于读者在配置和调试CAS SSO有更清晰的思路。

如果没记错,CAS协议应该是由Drew Mazurek负责可开发的,从CAS v1到现在的CAS v3,整个协议的基础思想都是基于Kerberos的票据方式。

   CAS v1非常原始,传送一个用户名居然是”yes"ndavid.turing”的方式,CAS v2开始使用了XML规范,大大增强了可扩展性,CAS v3开始使用AOP技术,让Spring爱好者可以轻松配置CAS Server到现有的应用环境中。

CAS是通过TGT(Ticket Granting Ticket)来获取ST(Service Ticket),通过ST来访问服务,而CAS也有对应TGTST的实体,而且他们在保护TGT的方法上虽然有所区别,但是,最终都可以实现这样一个目的——免去多次登录的麻烦。

  下面,我们看看 CAS 的基本协议框架:

2.1.1 基础协议

cas_protocol-1.jpg 
                                                 CAS 基础模式

  上图是一个最基础的CAS协议,CAS ClientFilter方式保护Web应用的受保护资源,过滤从客户端过来的每一个Web请求,同时,CAS Client会分析HTTP请求中是否包请求Service Ticket(上图中的Ticket),如果没有,则说明该用户是没有经过认证的,于是,CAS Client会重定向用户请求到CAS ServerStep 2)。Step 3是用户认证过程,如果用户提供了正确的CredentialsCAS Server会产生一个随机的Service Ticket,然后,缓存该Ticket,并且重定向用户到CAS Client(附带刚才产生的Service Ticket),Service Ticket是不可以伪造的,最后,Step 5Step6CAS ClientCAS Server之间完成了一个对用户的身份核实,用Ticket查到Username,因为TicketCAS Server产生的,因此,所以CAS Server的判断是毋庸置疑的。

  该协议完成了一个很简单的任务,就是User(david.turing)打开IE,直接访问helloservice应用,它被立即重定向到CAS Server进行认证,User可能感觉到浏览器在 helloservciecasserver之间重定向,但User是看不到,CAS ClientCAS Server相互间的Service Ticket核实(Validation)过程。当CAS Server告知CAS Client用户Service Ticket对应确凿身份,CAS Client才会对当前Request的用户进行服务。

2.2.2 CAS 如何实现SSO

  当我们的Web时代还处于初级阶段的时候,SSO是通过共享cookies来实现,比如,下面三个域名要做SSO

    http://www.blogjava.net

    http://www.matrix.org.cn

    http://www.csdn.net

  如果通过CAS来集成这三个应用,那么,这三个域名都要做一些域名映射,

    http://blogjava.cas.org

    http://matrix.cas.org

    http://csdn.cas.org

  因为是同一个域,所以每个站点都能够共享基于cas.orgcookies。这种方法原始,不灵活而且有不少安全隐患,已经被抛弃了。

  CAS可以很简单的实现跨域的SSO,因为,单点被控制在CAS Server,用户最有价值的TGC-Cookie只是跟CAS Server相关,CAS Server就只有一个,因此,解决了cookies不能跨域的问题。

  回到CAS的基础协议图,当Step3完成之后,CAS Server会向User发送一个Ticket granting cookie (TGC)User的浏览器,这个Cookie就类似KerberosTGT,下次当用户被Helloservice2重定向到CAS Server的时候,CAS Server 会主动 Get 到这个TGC cookie,然后做下面的事情:

  1, 如果 User 的持有 TGC 且其还没失效,那么就走基础协议图的 Step4 ,达到了 SSO 的效果。

  2,如果 TGC 失效,那么用户还是要重新认证 ( 走基础协议图的 Step3) 

2.2.2 CAS 的代理模式

  模式 1 已经能够满足大部分简单的SSO应用,现在,我们探讨一种更复杂的情况,即用户访问helloservicehelloservice又依赖于helloservice2 来获取一些信息,如同:

User à helloservice à helloservice2

这种情况下,假设 helloservice2 也是需要对User进行身份验证才能访问,那么,为了不影响用户体验(过多的重定向导致UserIE 窗口不停闪动)CAS引入了一种Proxy认证机制,即CAS Client可以代理用户去访问其它Web应用。

   代理的前提是需要CAS Client拥有用户的身份信息(类似凭据)与其说之前我们提到的TGC是用户持有对自己身份信息的一种凭据,则这里的PGT就是CAS Client端持有的对用户身份信息的一种凭据。凭借TGCUser可以免去输入密码以获取访问其它服务的Service Ticket,所以,这里,凭借PGTWeb应用可以代理用户去实现后端的认证,而无需前端用户的参与。

   如下面的CAS Proxy图所示,CAS Client在基础协议之上,提供了一个额外的 PGT URLCAS Server,于是,CAS Server可以通过PGT URL提供一个PGTCAS Client 

cas_protocol-2.jpg 
   初学者可能会对上图的PGT URL感到迷惑,或者会问,为什么要这么麻烦,要通过一个额外的 URL(而且是SSL的入口)去传递PGT?如果直接在Step 6返回,则连用来做对应关系的PGTIOU都可以省掉。PGTIOU设计是从安全性考虑的,非常必要,CAS协议安全性问题我会在后面一节介绍。

于是,CAS Client拿到了PGT(PGTIOU-85…..ti2td),这个 PGT  TGC 同样地关键,CAS Client可以通过PGT向后端Web应用进行认证。如下图所示,Proxy认证与普通的认证其实差别不大,Step1, 2与基础模式的Step 1,2几乎一样,唯一不同的是,Proxy模式用的是PGT而不是TGC,是Proxy TicketPT)而不是Service Ticket

最终的结果是,helloservice2明白helloservice所代理的客户是David. Turing 同学,同时,根据本地策略,helloservice2有义务为PGTURL=http://helloservice/proxy服务(PGTURL 用于表示一个Proxy服务),于是它传递数据给helloservice。这样,helloservice便完成一个代理者的角色,协助User返回他想要的数据。


cas_protocol-3.jpg 
  代理认证模式非常有用,它也是
CAS协议v2的一个最大的变化,这种模式非常适合在复杂的业务领域中应用SSO。因为,以前我们实施SSO的时候,都是假定以IE UserSSO的访问者,忽视了业务系统作为SSO的访问者角色。

2.3 术语和各术语之间关系解释

  CAS的核心就是其Ticket,及其在Ticket之上的一系列处理操作。CAS的主要票据有TGT、ST、PGT、PGTIOU、PT,其中TGT、ST是CAS1.0协议中就有的票据,PGT、PGTIOU、PT是CAS2.0协议中有的票据。

2.3.1术语
1. TGT(Ticket Grangting Ticket)
  TGT是CAS为用户签发的登录票据,拥有了TGT,用户就可以证明自己在CAS成功登录过。TGT封装了Cookie值以及此Cookie值对应的用户信息。用户在CAS认证成功后,CAS生成cookie(叫TGC),写入浏览器,同时生成一个TGT对象,放入自己的缓存,TGT对象的ID就是cookie的值。当HTTP再次请求到来时,如果传过来的有CAS生成的cookie,则CAS以此cookie值为key查询缓存中有无TGT ,如果有的话,则说明用户之前登录过,如果没有,则用户需要重新登录。

2. TGC (Ticket-granting cookie)
  存放用户身份认证凭证的cookie,在浏览器和CAS Server间通讯时使用,并且只能基于安全通道传输(Https),是CAS Server用来明确用户身份的凭证。

3. ST(Service Ticket)
  ST是CAS为用户签发的访问某一service的票据。用户访问service时,service发现用户没有ST,则要求用户去CAS获取ST。用户向CAS发出获取ST的请求,如果用户的请求中包含cookie,则CAS会以此cookie值为key查询缓存中有无TGT,如果存在TGT,则用此TGT签发一个ST,返回给用户。用户凭借ST去访问service,service拿ST去CAS验证,验证通过后,允许用户访问资源。

4. PGT(Proxy Granting Ticket)
  Proxy Service的代理凭据。用户通过CAS成功登录某一Proxy Service后,CAS生成一个PGT对象,缓存在CAS本地,同时将PGT的值(一个UUID字符串)回传给Proxy Service,并保存在Proxy Service里。Proxy Service拿到PGT后,就可以为Target Service(back-end service)做代理,为其申请PT。

5. PGTIOU(全称 Proxy Granting Ticket I Owe You)
  PGTIOU是CAS协议中定义的一种附加票据,它增强了传输、获取PGT的安全性。
PGT的传输与获取的过程:Proxy Service调用CAS的serviceValidate接口验证ST成功后,CAS首先会访问pgtUrl指向的https url,将生成的 PGT及PGTIOU传输给proxy service,proxy service会以PGTIOU为key,PGT为value,将其存储在Map中;然后CAS会生成验证ST成功的xml消息,返回给Proxy Service,xml消息中含有PGTIOU,proxy service收到Xml消息后,会从中解析出PGTIOU的值,然后以其为key,在map中找出PGT的值,赋值给代表用户信息的Assertion对象的pgtId,同时在map中将其删除。

6. PT(Proxy Ticket)
  PT是用户访问Target Service(back-end service)的票据。如果用户访问的是一个Web应用,则Web应用会要求浏览器提供ST,浏览器就会用cookie去CAS获取一个ST,然后就可以访问这个Web应用了。如果用户访问的不是一个Web应用,而是一个C/S结构的应用,因为C/S结构的应用得不到cookie,所以用户不能自己去CAS获取ST,而是通过访问proxy service的接口,凭借proxy service的PGT去获取一个PT,然后才能访问到此应用。


2.3.2 TGT、ST、PGT、PT之间关系
1. ST是TGT签发的。用户在CAS上认证成功后,CAS生成TGT,用TGT签发一个ST,ST的ticketGrantingTicket属性值是TGT对象,然后把ST的值redirect到客户应用。
2.  PGT是ST签发的。用户凭借ST去访问Proxy service,Proxy service去CAS验证ST(同时传递PgtUrl参数给CAS),如果ST验证成功,则CAS用ST签发一个PGT,PGT对象里的ticketGrantingTicket是签发ST的TGT对象。
3. PT是PGT签发的。Proxy service代理back-end service去CAS获取PT的时候,CAS根据传来的pgt参数,获取到PGT对象,然后调用其grantServiceTicket方法,生成一个PT对象。

2.3.3 其它说明如下
1. Ticket Granting ticket(TGT) :票据授权票据,由 KDC 的 AS 发放。即获取这样一张票据后,以后申请各种其他服务票据 (ST) 便不必再向 KDC 提交身份认证信息 (Credentials) ;
2. Authentication service(AS) --------- 认证用服务,索取 Credentials ,发放 TGT ;
3. Ticket-granting service (TGS) --------- 票据授权服务,索取 TGT ,发放 ST ;
4. KDC( Key Distribution Center ) ---------- 密钥发放中心。

2.4 CAS安全性

   CAS的安全性是一个非常重要的Topic CASv1v3,都很依赖于SSL,它假定了这样一个事实,用户在一个非常不安全的网络环境中使用SSOHackerSniffer会很容易抓住所有的Http Traffic,包括通过Http传送的密码甚至Ticket票据。

2.4.1 TGC/PGT 安全性

  对于一个CAS用户来说,最重要是要保护它的TGC,如果TGC不慎被CAS Server以外的实体获得,Hacker能够找到该TGC,然后冒充CAS用户访问所有授权资源。

   SSO的安全性问题比普通应用的安全性还要严重,因为SSO存在一种门槛效应。以前即使Hacker能够截获用户在Web应用A的密码,它也未必能知道用户在Web应用B的密码,但SSOHacker只需要截获TGC(突破了门槛),即能访问所有与该用户相关的所有应用系统。

   PGTTGC的角色是一样的,如果被Hacker获得,后果可想而知。

  从基础模式可以看出,TGCCAS Server通过SSL方式发送给终端用户,因此,要截取 TGC 难度非常大,从而确保 CAS 的安全性。

  因此,某些人认为CAS可以不使用SSL的想法需要更正一下,CAS的传输安全性仅仅依赖与SSL

  Kerberos一样TGTTGC也有自己的存活周期。下面是CASweb.xml中,通过grantingTimeout来设置CAS TGC存活周期的参数,参数默认是 120 分钟,在合适的范围内设置最小值,太短,会影响 SSO 体验,太长,会增加安全性风险。

edu.yale.its.tp.cas.grantingTimeout  7200

TGC 面临的风险主要并非传输窃取。比如你登陆了之后,没有Logout,离开了电脑,别人就可以打开你的浏览器,直接访问你授权访问的应用),设置一个TGC的有效期,可以减少被别人盗用,或者被Hacker入侵你的电脑直接获取你系统目录下的TGC Cookie

2.4.2 Service Ticket/Proxy Ticket 安全性

  首要明白,Service Ticket是通过Http 传送的,以为着所网络中的其他人可以Sniffer到其他人的Ticket

CAS协议从几个方面让Service Ticket变得更加安全。

l         Service Ticket只能使用一次。

CAS协议规定,无论Service Ticket验证是否成功,CAS Server都会将服务端的缓存中清除该Ticket,从而可以确保一个Service Ticket被使用两次。

l         Service Ticket在一段时间内失效。

假设用户拿到Service Ticket之后,他请求helloservice的过程又被中断了,Service Ticket就被空置了,事实上,此时,Service Ticket仍然有效。CAS规定 Service Ticket只能存活一定的时间,然后CAS Server会让它失效。通过在web.xml中配置下面的参数,可以让Service Ticket在多少秒内失效。

edu.yale.its.tp.cas.serviceTimeout 300

  该参数在业务应用的条件范围内,越小越安全。

l         Service Ticket 是基于随机数生成的。

Service Ticket必须足够随机,如果Service Ticket生成规则被猜出(如果你使用了ST+Helloservice+自增序列的方式,Hacker就可以构造下一个Ticket),Hacker就等于绕过CAS认证,直接访问所有服务。 
===============================
===============================
===============================
http://blog.csdn.net/hongbinchen/article/details/6745656

yale cas可以百度一下,这是学习cas后的一点总结,以备日后使用!

安全性:

用户只须在cas录入用户名和密码,之后通过ticket绑定用户,在cas客户端与cas校验是通过ticket,并不会在网上传输密码,所以可以保证安全性,密码不被窃取

原理:1个cookie+N个session

CAS创建cookie在所有应用中登录时cas使用,各应用通过在IE创建各自的session来标识应用是否已经登录。

Cookie:在cas为各应用登录时使用,实现了只须一次录入用户密码

Session:各应用会创建自己的session表示是否登录

登录

登录原理版本1:

1. CAS 登录时处理:

第一步:cas往浏览器增加cookie(TGC)

CAS向浏览器送回一个所谓的“内存cookie”。这种cookie并不是真的保存在内存中,而只是浏览器一关闭,cookie就自动过期。这个cookie称为“ticket-granting cookie”,用来表明用户已经成功地登录。

这个Cookie是一个加密的Cookie,其中保存了用户登录的信息。用于以后其它应用客户端登录。

第二步:cas同时创建一个ticket重定向到原来的cas客户端

认证成功后,CAS服务器创建一个很长的、随机生成的字符串,称为“Ticket”。随后,CAS将这个ticket和成功登录的用户,以及服务联系在一起。这个ticket是一次性使用的一种凭证,它只对登录成功的用户及其服务使用一次。使用过以后立刻失效。

2. Cas 客户端应用的处理

第一步:收到ticket后,向cas提交验证ticket

Cas客户端收到ticket之后,应用程序需要验证ticket。这是通过将ticket 传递给一个校验URL来实现的。校验URL也是CAS服务器提供的。CAS通过校验路径获得了ticket之后,通过内部的数据库对其进行判断。如果判断是有效性,则返回一个NetID给应用程序。随后CAS将ticket作废,并且在客户端留下一个cookie。(谁来创建cookie?),

第二步:ticket验证后创建session

   以后登录此应用时,没有ticket,但IE能提供session,从session中取得CASReceipt,并验证如果有效说明已经在此应用认证过,允许访问此应用,

   到此为止,CAS会记录用户已在应用A已经登录

3. 用户登录到应用是如何处理

  用户进入应用B时,首先仍然会重定向到CAS服务器。不过此时CAS服务器不再要求用户输 入用户名和密码,而是首先自动寻找Cookie,根据Cookie中保存的信息,进行登录。然后,CAS同样给出新的ticket重定向应用B给cas验证(流程同应用A验证方式),如果验证成功则应用B创建session记录CASReceipt信息到session中,以后凭此session登录应用B。

到此为止,CAS会记录用户已在应用A和应用B进行登录,但是当用户在应用B退出cas登录时,要通知应用A进行退出,如何通知应用A呢?下面会讲解.

登录原理版本2:

  用户第一次访问一个CAS 服务的客户web 应用时(访问URL :http://localhost:8180/cas_app1 ),部署在客户web 应用的cas AuthenticationFilter ,会截获此请求,生成service 参数,然后redirect 到CAS 服务的login 接口,url为http://cas.itcast.cn/login?service=http%3A%2F%2Flocalhost%3A8180%2Fcas_app1%2F,认证成功后,CAS 服务器会生成认证cookie ,写入浏览器,同时将cookie 缓存到服务器本地,CAS 服务器还会根据service 参数生成ticket,ticket 会保存到服务器,也会加在url 后面,然后将请求redirect 回客户web 应用,url 为http://192.168.1.90:8081/web1/?ticket=ST-5-Sx6eyvj7cPPCfn0pMZuMwnbMvxpCBcNAIi6-20 。这时客户端的AuthenticationFilter 看到ticket 参数后,会跳过,由其后面的TicketValidationFilter 处理,TicketValidationFilter 会利用httpclient 工具访问cas 服务的/serviceValidate 接口,将ticket 、service 都传到此接口,由此接口验证ticket 的有效性,TicketValidationFilter 如果得到验证成功的消息,就会把用户信息写入web 应用的session里。至此为止,SSO 会话就建立起来了,以后用户在同一浏览器里访问此web 应用时,AuthenticationFilter 会在session 里读取到用户信息,所以就不会去CAS 认证,如果在此浏览器里访问别的web 应用时,AuthenticationFilter 在session 里读取不到用户信息,会去CAS 的login 接口认证,但这时CAS 会读取到浏览器传来的cookie ,所以CAS 不会要求用户去登录页面登录,只是会根据service 参数生成一个ticket ,然后再和web 应用做一个验证ticket 的交互。


登出

\

  用户执行登出操作,当前应用服务器会把这个登出请求重定向到CAS server,CAS server接受登出请求后,会检测用户的TCG Cookie,把对应的session清除,同时会找到所有通过该TGC sso登录的应用服务器URL提交请求,所有的回调请求中,包含一个参数logoutRequest,访问这个登出URL,
所有收到请求的应用服务器(就是是CAS client)会解析这个参数,取得sessionId,根据这个Id取得session后,把session删除。这样就实现单点登出的功能,用户无法在这个具体应用上继续操作了,只能重新登录才行。

  注销的Filter要在其它Filter之前,界面的注销连接到CAS的logout地址,如http://localhost:8080/cas/logout

  SingleSignOutFilter,主要是在有ticket参数的时候,将session放到sessionMappingStorage,如果参数中存在logoutRequest,则注销session,那什么时候去注销sessionMappingStorage的东西呢?这是靠SingleSignOutHttpSessionListener来实现的,当有session被销毁的时候,触发将sessionMappingStorage中对应sessionid中的数据删除。

  所以在配置单点登出的时候,一定要配置这个监听器,否则客户端很容易导致内存溢出的。让我们先来看看SingleSignOutFilter的整体逻辑。

知道原理后,下面是结合源代码来讲述一下内部的代码怎么实现的。

客户端实现:

首先,要实现single sign out在 应用服务器application端的web.xml要加入以下配置

<filter>   <filter-name>CAS Single Sign Out Filterfilter-name>   <filter-class>org.jasig.cas.client.session.SingleSignOutFilterfilter-class>filter><filter-mapping>   <filter-name>CAS Single Sign Out Filterfilter-name>   <url-pattern>/*url-pattern>filter-mapping><listener>    <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListenerlistener-class>listener>


注:如果有配置CAS client Filter,则CAS Single Sign Out Filter 必须要放到CAS client Filter之前。

配置部分的目的是在CAS server回调所有的application进行单点登出操作的时候,需要这个filter来实现session清楚。

主要代码如下:
org.jasig.cas.client.session.SingleSignOutFilter

public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;if ("POST".equals(request.getMethod())) {final String logoutRequest = request.getParameter("logoutRequest");if (CommonUtils.isNotBlank(logoutRequest)) {if (log.isTraceEnabled()) {log.trace("Logout request=[" + logoutRequest + "]");}// 从xml中解析 SessionIndex key值final String sessionIdentifier = XmlUtils.getTextForElement(logoutRequest, "SessionIndex");if (CommonUtils.isNotBlank(sessionIdentifier)) {// 根据sessionId取得session对象final HttpSession session = SESSION_MAPPING_STORAGE.removeSessionByMappingId(sessionIdentifier);if (session != null) {String sessionID = session.getId();if (log.isDebugEnabled()) {log.debug("Invalidating session [" + sessionID+ "] for ST [" + sessionIdentifier + "]");}try {// 让session失效session.invalidate();} catch (final IllegalStateException e) {log.debug(e, e);}}return;}}} else {// get方式 表示登录,把session对象放到SESSION_MAPPING_STORAGE(map对象中)final String artifact = request.getParameter(this.artifactParameterName);final HttpSession session = request.getSession();if (log.isDebugEnabled() && session != null) {log.debug("Storing session identifier for " + session.getId());}if (CommonUtils.isNotBlank(artifact)) {SESSION_MAPPING_STORAGE.addSessionById(artifact, session);}}filterChain.doFilter(servletRequest, servletResponse);}


SingleSignOutHttpSessionListener实现了javax.servlet.http.HttpSessionListener接口,用于监听session销毁事件

public final class SingleSignOutHttpSessionListener implements HttpSessionListener {  private Log log = LogFactory.getLog(getClass());  private SessionMappingStorage SESSION_MAPPING_STORAGE;      public void sessionCreated(final HttpSessionEvent event) {    // nothing to do at the moment}  //session销毁时 public void sessionDestroyed(final HttpSessionEvent event) {     if (SESSION_MAPPING_STORAGE == null) {//如果为空,创建一个sessionMappingStorage 对象         SESSION_MAPPING_STORAGE = getSessionMappingStorage();     }     final HttpSession session = event.getSession();//取得当然要销毁的session对象          if (log.isDebugEnabled()) {         log.debug("Removing HttpSession: " + session.getId());     }     //从SESSION_MAPPING_STORAGE map根据sessionId移去session对象     SESSION_MAPPING_STORAGE.removeBySessionById(session.getId()); }   /**   * Obtains a {@link SessionMappingStorage} object. Assumes this method will always return the same   * instance of the object.  It assumes this because it generally lazily calls the method.   *   * @return the SessionMappingStorage  */     protected static SessionMappingStorage getSessionMappingStorage() {     return SingleSignOutFilter.getSessionMappingStorage();     }}


 服务器端实现

 已经登录的应用会在服务器端保存,所以服务端分别对各个应用发送http请求进行session清除操作。

网上参考资料

看了下面的浏览器cookie变化,会对cas有更深的理解

下载个httpwatch监控一下cookie的变化

客户端消息流程

1. 第一次访问http://localhost:8080/a,

  CLIENT:没票据且SESSION中没有消息所以跳转至CAS

  CAS:拿不到TGC故要求用户登录

2. 认证成功后回跳

  CAS:通过TGT生成ST发给客户端,客户端保存TGC,并重定向到http://localhost:8080/a

  CLIENT:带有票据所以不跳转只是后台发给CAS验证票据(浏览器中无法看到这一过程)

3. 第一次访问http://localhost:8080/b

  CLIENT:没票据且SESSION中没有消息所以跳转至CAS

  CAS:从客户端取出TGC,如果TGC有效则给用户ST并后台验证ST,从而SSO。【如果失效重登录或注销时,怎么通知其它系统更新SESSION信息呢??TicketGrantingTicketImpl类grantServiceTicket方法里this.services.put(id,service);可见CAS端已经记录了当前登录的子系统】

4. 再次访问http://localhost:8080/a

  CLIENT:没票据但是SESSION中有消息故不跳转也不用发CAS验证票据,允许用户访问


注:以上内容根据网络内容整理而成,如果侵犯到您的权益,请联系我

参考文档:

http://www.cnblogs.com/prctice/p/5772701.html

http://blog.chinaunix.net/uid-22816738-id-3525939.html

http://www.cnblogs.com/hubaoxi/p/4977058.html

http://www.2cto.com/kf/201403/289366.html

1 0
原创粉丝点击