其实这个cache怎么用已经在cas中给出了,站在巨人的肩膀上说一下:
首先ticket的作用可以在cas的流程里看出来,如下:
用户第一次访问一个CAS 服务的客户web 应用时(访问URL :http://192.168.1.90:8081/web1 ),部署在客户web 应用的cas AuthenticationFilter ,会截获此请求,生成service 参数,然后redirect 到CAS 服务的login 接口,url为https://cas:8443/cas/login?service=http%3A%2F%2F192.168.1.90%3A8081%2Fweb1%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 的交互。
ticket对象默认默认是存在一个ConcurrentHashMap中的,key为ticket的id,value为ticket对象,cas默认处理ticket的对象是使用quartz(魔兽世界有个插件也quartz,lua写的)这个神奇的第三方jar,quartz比jdk提供的timer要强大,timer只可以重复一定间隔执行一个任务,quartz可以每天定时定点的执行一个任务,作为一个“最”完美的框架,spring当然也提供了对quartz的支持,先来看cas默认的ticketRegistry.xml,这个是配置ticket存储和清除策略的配置文件,
<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" />
<!--Quartz -->
<!-- TICKET REGISTRY CLEANER -->
<bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
p:ticketRegistry-ref="ticketRegistry" />
<bean id="jobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref="ticketRegistryCleaner"
p:targetMethod="clean" />
<bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
p:jobDetail-ref="jobDetailTicketRegistryCleaner"
p:startDelay="20000"
p:repeatInterval="5000000" />
第一个id为ticketRegistry的bean持有存放ticket的hashmap,并且有增加、删除覆盖ticket的方法,第二个ticketRegistryCleaner的bean则是清除特定ticket的一个类,只有一个clean方法,jobDetailTicketRegistryCleaner则是调用ticketRegistryCleaner的clean方法的工厂bean,之后由simpletriggerbean来触发,startDelay为触发时间,repeatInterval为触发间隔,单位都是毫秒。
如果要做集群的话,这个方法就行不通了,为神马,因为集群只是共享session,ticket没有存储到session,所以就要依赖于第三方的缓存方案了,cas支持jbosstreecache,ehcache,memcached等cache,如果要使用cache(这里以jbosstreecache为例)需要修改上述 ticketRegistry.xml配置文件,如下:
<bean id="ticketRegistry"
class="org.jasig.cas.ticket.registry.JBossCacheTicketRegistry">
<property name="cache" ref="cache" />
</bean>
<bean id="cache" class="org.jasig.cas.util.JBossCacheFactoryBean">
<property name="configLocation"
value="classpath:jbossCacheCluster.xml" />
</bean>
JBossCacheTicketRegistry是另一种注册ticket的类,同样有添加、删除、覆盖ticket的方法,只不过它被注入一个cache对象,这个cache对象就是jbosstreecache, this.cache.put(FQN_TICKET, ticket.getId(), ticket)调用了它的put方法放入ticket,但是这个cache对象怎么获得的,因为jboss提供的是一个配置文件一个jar包,我们怎么把它转换为cache对象,cas给出了答案(其实官网和网上都有好多,只不过没看,想等到以后碰到再弄,我对自己有十足信心),cas提供了一个JBossCacheFactoryBean类,它有一个属性,注入的是jbossCacheCluster.xml这个配置文件,类型为spring的ClassPathResource,调用了它的getInputStream()方法得到xml文件的输入流
,看一看JBossCacheFactoryBean的代码,关键代码只有下面两行你敢信,
final CacheFactory<String, Ticket> cf = new DefaultCacheFactory<String, Ticket>();//这是jboss的api,创建一个工厂对象
this.cache = cf.createCache(this.configLocation.getInputStream()); //拿到配置文件的输入流创建cache对象
至此cache的神秘面纱被揭开了,你只需要配置并且写几行代码放入你想要放进缓存的对象,这个缓存方案就会为你所用,开源的伟大就在于此!
总结:我已经觉得自己很勤奋,其实不是,因为今天我发现一个spring的一些spring webflow标签我一个月之前就看见了,但我今天才花功夫去弄明白,自己还是太懒了,也太分神了,因为每天又要去搞服务器,debug,写代码,总结,写文章!但是这一切都是为以后做铺垫的!
如果有空,今年年底我想玩转python!!!let’s code!!!
cas再一次告诉我们,spring就是最完美的框架,struts2停止更新,现网可能bug一堆,所以我%99会选择spring mvc来取代它(如果我可以替老板做决定的话),至于数据库框架,很久没看了,不过随着自己思想的提升,我更关心orm框架是怎么使用上述的缓存来实现性能提升的。
再一次高呼:spring in action!