SSO单点登录系列6:cas单点登录防止登出退出后刷新后退ticket失效报500错

这个问题之前就发现过,最近有几个哥们一直在问我这个怎么搞,我手上在做另一个项目,cas就暂时搁浅了几周。现在我们来一起改一下你的应用(client2/3)的web.xml来解决这个2b问题,首先看下错误描述:

问题: 我登录了client2,又登录了client3,现在我把client2退出了,在client3里面我F5刷新了一下,结果页面报错:

未能够识别出目标 'ST-41-2VcnVMguCDWJX5zHaaaD-cas01.example.org'票根

type Exception report

message org.jasig.cas.client.validation.TicketValidationException:

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: org.jasig.cas.client.validation.TicketValidationException: 
		鏈兘澶熻瘑鍒嚭鐩爣 'ST-41-2VcnVMguCDWJX5zHaaaD-cas01.example.org'绁ㄦ牴
	
	org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:155)
	org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:99)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
root cause

org.jasig.cas.client.validation.TicketValidationException: 
		鏈兘澶熻瘑鍒嚭鐩爣 'ST-41-2VcnVMguCDWJX5zHaaaD-cas01.example.org'绁ㄦ牴
	
	org.jasig.cas.client.validation.Cas20ServiceTicketValidator.parseResponseFromServer(Cas20ServiceTicketValidator.java:73)
	org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:188)
	org.jasig.cas.client.validation.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:132)
	org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:99)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.37 logs.

SSO单点登录系列6:cas单点登录防止登出退出后刷新后退ticket失效报500错_第1张图片

猜都能猜出来,我注销了,ticket已经失效了,现在我又发回到server端,它就报错了。(客户端发过去就报错了),以下就是cas ticket失效处理的一个很简单的解决办法,复杂的话,需要修改client源码进行异常处理。


1.所以针对这个情况,我只能在web.xml中下手了,(你也可以修改客户端的jar包中的一些java类,自己去做这个异常处理,接收所有在cas使用过程中会出错的处理,全部跳转到错误页面中,让掉线的人重新登录。在这里,我们采用web.xml配置一下)


2.这是官网解释:https://wiki.jasig.org/display/CASC/Configuring+the+Jasig+CAS+Client+for+Java+in+the+web.xml 它的解释:

The correct order of the filters in web.xml is necessary:

  1. AuthenticationFilter
  2. TicketValidationFilter (whichever one is chosen)
  3. HttpServletRequestWrapperFilter
  4. AssertionThreadLocalFilter


意思是说,过滤器链不要错,我之前的那篇教程里cas客户端配置web.xml没有使用这几个过滤器,现在我们重新使用它。


3.这是一个哥们之前解释的:我贴出来。

单点登出,客户端配置。我尝试使用SAML作为认证和Ticket校验,但是调试时发现单点登出取标识的方式只能识别CAS的认证和校验。
认证:org.jasig.cas.client.authentication.AuthenticationFilter
校验:org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
过滤器顺序:
1. CAS Single Sign Out Filter
2. CAS Validation Filter
3. CAS Authentication Filter
4. CAS HttpServletRequest Wrapper Filter
5. CAS Assertion Thread Local Filter
特别注意Validation在Authentication之前,因为我使用的是Cas20ProxyReceivingTicketValidationFilter。根据CAS文档描述:If you are using proxy validation, you should map the validation filter before the authentication filter.


4.ok,放上我的web.xml文件,废掉之前的cas验证过滤器(CAS Filter)。使用另一个过滤器(CAS Authentication Filter),并且增加另外三个过滤器(CAS Validation Filter,CAS HttpServletRequest Wrapper Filter,CAS Assertion Thread Local Filter),注意过滤器的顺序.




    
    
        spring filter
        
			org.springframework.web.filter.CharacterEncodingFilter
        
        
            encoding
            UTF-8
        
    
    
        spring filter
        /*
    
    


    
    
        
			org.jasig.cas.client.session.SingleSignOutHttpSessionListener
        
    

    
        CAS Single Sign Out Filter
        
			org.jasig.cas.client.session.SingleSignOutFilter
        
    

    
        CAS Single Sign Out Filter
        /*
    



    
    
        CAS Validation Filter
        
			org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
        
        
            casServerUrlPrefix
            
				http://192.168.168.141:8080/casServer
            
        
        
            serverName
            192.168.168.141:8080
        
        
            useSession
            true
        

        
            exceptionOnValidationFailure
            false
        

        
            redirectAfterValidation
            true
        
    

    
        CAS Validation Filter
        /*
    

    

    
        CAS Authentication Filter
        
			org.jasig.cas.client.authentication.AuthenticationFilter
        
        
            casServerLoginUrl
            
				http://192.168.168.141:8080/casServer/login
            
        
        
            serverName
            http://192.168.168.141:8080
        
    
    
        CAS Authentication Filter
        /*
    



    


    

    
        CAS HttpServletRequest Wrapper Filter
        
			org.jasig.cas.client.util.HttpServletRequestWrapperFilter
        
    

    
        CAS HttpServletRequest Wrapper Filter
        /*
    


    

    
        CAS Assertion Thread Local Filter
        
			org.jasig.cas.client.util.AssertionThreadLocalFilter
        
    

    
        CAS Assertion Thread Local Filter
        /*
    


    
        Query
        servlet.Query
    

    
        Query
        /query
    

    
        index.jsp
    


5.如果这样做了,你还需要一件事情,就是前台获取用户信息的方式改了,我的index.jsp改成了这个:


<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@page import="edu.yale.its.tp.cas.client.filter.CASFilter"%>
<%@page import="org.jasig.cas.client.util.AssertionThreadLocalFilter"%>
<%@page import="org.jasig.cas.client.util.HttpServletRequestWrapperFilter"%>
<%@page import="org.jasig.cas.client.authentication.AttributePrincipal"%>
<%@page import="org.jasig.cas.client.util.AbstractCasFilter"%>
<%@page import="org.jasig.cas.client.validation.Assertion"%>




		

登录成功,这是客户端2


欢迎您: <% //String username = (String) session.getAttribute(CASFilter.CAS_FILTER_USER); //String username2 = (String)AssertionHolder.getAssertion().getPrincipal().getName(); String username = ""; AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal(); if(principal != null){ username = principal.getName();//获取用户名 } %> 用户名:<%=username%>

ok,我的应用之间如果一个退出,另一个就算带ticket参数也不不再报错了,就算是测试组的兄弟拿到那段ticket复制粘贴到另一个浏览器中进行访问,也不会报错。


ps:

也有兄弟说可以通过修改C:\tomcat7\webapps\casServer\WEB-INF\spring-configuration\ticketExpirationPolicies.xml这个文件中的


  
    
    
其中那个

 c:numberOfUses="1" //使用ticket多少次

 c:timeToKill="${st.timeToKillInSeconds:10}" //多少秒过期,默认10秒,你把这个改成10分钟玩玩。

这个方法我没有尝试,所以希望想尝试想折腾和想玩的兄弟狠狠的点击这个链接:http://bbs.csdn.net/topics/390111112


落雨

 2013年7月26日13:37:05

你可能感兴趣的:(SSO单点登录系列)