CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

Richaaaard發表於2015-12-22

CAS (7) —— Mac下配置CAS 4.x叢集及JPATicketRegistry(服務端)


tomcat版本: tomcat-8.0.29

jdk版本: jdk1.8.0_65

cas版本:

cas4.1.3 (4.x還在開發過程中不是很穩定,迭代比較快,也會有些bug)

cas-client-3.4.1

參考來源:

Jasig: 4.1.x JPA Ticket Registry

Jasig: 4.1.3 JPA Ticket Registry

百度文庫: CAS JPA-Ticket儲存解決負載均衡配置

CSDN: cas 入門之十五:ticket 儲存方案-jpa ticket儲存 (3.x版本有點老)

Stackoverflow: Jasig CAS. How to enable transactions with JpaTicketRegistry?

Stackoverflow: TransactionRequiredException: No transactional EntityManager available within @Transactional method

目標架構

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

準備

參照以下文章首先準備好如下圖的環境

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

檢查列表

  • CAS Client A - app1.hoau.com:8413 (node-a)
  • CAS Client B - app2.hoau.com:8423 (node-b)
  • CAS Server A - sso.hoau.com:8433 (node-c)
  • CAS Server B - sso.hoau.com:8443 (node-d)
  • Nginx - Load Balancer

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

配置

接文章(CAS (5) —— Nginx代理模式下瀏覽器訪問CAS伺服器配置詳解)之後,我們嘗試為CAS
服務配置多個節點。

如若要想實現CAS叢集,關於RegistryTicket可以有多種處理方式:

  1. Tomcat Session Replication (預設狀態下,Ticket資訊是儲存與Session之中的)
  2. 獨立的快取儲存方案
    • Memcached
    • Ehcache
    • Redis
  3. 資料庫儲存JpaTicketRegistry

*注意:本篇文章主要關注的是JpaTicketRegistry這種方式再叢集環境下的解決方案

當我們實現了用Nginx代理轉發到node-c,併成功實現app1.hoau.com與app2.hoau.com的SSO後,以node-c的配置為例,我們配置好node-d,並且開啟nginx的Load Balancer和Sticky Session

  • nginx.conf

upstream

upstream cas_server_ssl {  
    server sso.hoau.com:8433 weight=1 srun_id=cas-tomcat-c; 
    server sso.hoau.com:8443 weight=1 srun_id=cas-tomcat-d; 
    jvm_route $cookie_JSESSIONID|sessionid reverse;
}  

*注意:以上配置中的jvm_route和srun_id,其中srun_id需要和node-c和node-d中的Catalina server.xml配置一致

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

server

server { 
    listen 443;
    server_name  proxy.sso.hoau.com;
    ssl on; 
    ssl_certificate /Users/Richard/Documents/Dev/servers/cluster/nginx/keys/server.crt; 
    ssl_certificate_key  /Users/Richard/Documents/Dev/servers/cluster/nginx/keys/server.key; 

    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers on;

    location / {
        #root   html;
        #index  index.html index.htm index.jsp;
        proxy_redirect off;  

        proxy_set_header Host $host;  
        proxy_set_header   Referer $http_referer;
        proxy_set_header   Cookie $http_cookie;
        proxy_set_header X-Real-IP $remote_addr;  
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-FORWARDED-HOST $server_addr;  
        proxy_set_header X-FORWARDED-PORT $server_port;

        proxy_connect_timeout 3;
        proxy_send_timeout 30;
        proxy_read_timeout 30;

        proxy_pass https://cas_server_ssl;
      }
}

如果此時嘗試測試系統,可能會出現以下錯誤,原因是因為兩個CAS Server的Session不共享,隨機生成的Ticket並不能在兩個不同的CAS Server環境下同時使用。

javax.servlet.ServletException: org.jasig.cas.client.validation.TicketValidationException:
    Ticket 'ST-1-9yxMX3RGh9helSCSwNTb-cas01.sso.hoau.com' not recognized

org.jasig.cas.client.validation.AbstractTicketValidatorFilter.doFilter(AbstractTicketValidationFilter.java:227)

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

*注意: 這是我們嘗試配置JpaTicketRegistry的初衷(當然也可以通過上述的多種方式都能解決此問題)

  • ticketRegistry.xml

以下是4.1.x官方文件給出來的示例配置,在4.1.x後CAS將以前@Transactional的註解方式更改成了下面推薦的這種aop方式,但是下面的配置對於4.1.2/4.1.3這兩個版本缺少了一點東西,執行時可能會遇到錯誤。

<bean
        id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource"
        p:driverClass="${database.driverClass:org.hsqldb.jdbcDriver}"
        p:jdbcUrl="${database.url:jdbc:hsqldb:mem:cas-ticket-registry}"
        p:user="${database.user:sa}"
        p:password="${database.password:}"
        p:initialPoolSize="${database.pool.minSize:6}"
        p:minPoolSize="${database.pool.minSize:6}"
        p:maxPoolSize="${database.pool.maxSize:18}"
        p:maxIdleTimeExcessConnections="${database.pool.maxIdleTime:1000}"
        p:checkoutTimeout="${database.pool.maxWait:2000}"
        p:acquireIncrement="${database.pool.acquireIncrement:16}"
        p:acquireRetryAttempts="${database.pool.acquireRetryAttempts:5}"
        p:acquireRetryDelay="${database.pool.acquireRetryDelay:2000}"
        p:idleConnectionTestPeriod="${database.pool.idleConnectionTestPeriod:30}"
        p:preferredTestQuery="${database.pool.connectionHealthQuery:select 1}"
/>

<bean id="ticketRegistry" class="org.jasig.cas.ticket.registry.JpaTicketRegistry" />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

<util:list id="packagesToScan">
    <value>org.jasig.cas.ticket</value>
    <value>org.jasig.cas.adaptors.jdbc</value>
</util:list>

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
      id="jpaVendorAdapter"
      p:generateDdl="true"
      p:showSql="true" />

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      p:dataSource-ref="dataSource"
      p:jpaVendorAdapter-ref="jpaVendorAdapter"
      p:packagesToScan-ref="packagesToScan">
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${database.dialect:org.hibernate.dialect.HSQLDialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
            <prop key="hibernate.jdbc.batch_size">${database.batchSize:1}</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
      p:entityManagerFactory-ref="entityManagerFactory" />

<tx:advice id="txRegistryAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="deleteTicket" read-only="false" />
        <tx:method name="addTicket" read-only="false" />
        <tx:method name="updateTicket" read-only="false" />
        <tx:method name="getTicket" read-only="true" />
        <tx:method name="getTickets" read-only="true" />
        <tx:method name="sessionCount" read-only="true" />
        <tx:method name="serviceTicketCount" read-only="true" />
    </tx:attributes>
</tx:advice>

<tx:advice id="txRegistryLockingAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="getOwner" read-only="true" />
        <tx:method name="acquire" read-only="false" />
        <tx:method name="release" read-only="false" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="ticketRegistryOperations" expression="execution(* org.jasig.cas.ticket.registry.JpaTicketRegistry.*(..))"/>
    <aop:pointcut id="ticketRegistryLockingOperations" expression="execution(* org.jasig.cas.ticket.registry.support.JpaLockingStrategy.*(..))"/>
    <aop:advisor advice-ref="txRegistryAdvice" pointcut-ref="ticketRegistryOperations"/>
    <aop:advisor advice-ref="txRegistryLockingAdvice" pointcut-ref="ticketRegistryLockingOperations"/>
</aop:config>


<bean id="ticketRegistryCleaner"
      class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
      c:centralAuthenticationService-ref="centralAuthenticationService"
      c:ticketRegistry-ref="ticketRegistry"
      p:lock-ref="cleanerLock"/>

<bean id="cleanerLock" class="org.jasig.cas.ticket.registry.support.JpaLockingStrategy"
      p:uniqueId="${host.name}"
      p:applicationId="cas-ticket-registry-cleaner" />

<bean id="jobDetailTicketRegistryCleaner"
      class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
      p:targetObject-ref="ticketRegistryCleaner"
      p:targetMethod="clean" />

<bean id="triggerJobDetailTicketRegistryCleaner"
      class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"
      p:jobDetail-ref="jobDetailTicketRegistryCleaner"
      p:startDelay="20000"
      p:repeatInterval="5000000" />

*注意: 如果使用MySQL5.x以上的entityManagerFactory需要修改,這在多數論壇文章中都能找到

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      p:dataSource-ref="ticketDataSource"
      p:jpaVendorAdapter-ref="jpaVendorAdapter"
      p:packagesToScan-ref="packagesToScan">
    <property name="persistenceUnitName" value="CasPU"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

這裡比較重要的是hibernate.dialect需要根據目標資料庫配置,另外hibernate.hbm2ddl.auto是給JPATicketRegistry賦予相應許可權的,因為在服務啟動時,系統會自動檢測目標資料庫中,是否含有相應表的資訊,如果沒有,則會執行ddl指令碼建立表:

  • locks
  • SERVICETICKET
  • TICKETGRANTINGTICKET

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

關於鎖的策略(Cleaner Locking Strategy)

4.1.x版本提供了JpaLockingStrategy,來支援exclusive non-reentrant lock

This will configure the cleaner with the following defaults:

tableName = “LOCKS”

uniqueIdColumnName = “UNIQUE_ID”

applicationIdColumnName = “APPLICATION_ID”

expirationDataColumnName = “EXPIRATION_DATE”

platform = SQL92

lockTimeout = 3600 (1 hour)

為了降低死鎖出現的概率需要新增以下索引

MySQL

CREATE INDEX ST_TGT_FK_I ON SERVICETICKET (ticketGrantingTicket_ID);
CREATE INDEX ST_TGT_FK_I ON TICKETGRANTINGTICKET (ticketGrantingTicket_ID);

以上這些內容,都能在官方文件中找到,還有其他相關的重要說明,在此不贅述。

*注意: 如果這樣配置完畢,然後充其伺服器進行測試,會遇到以下錯誤

org.jasig.cas.web.flow.GenerateServiceTicketAction@7c10e841 in state 'generateServiceTicket' of flow 'login' -- action execution attributes were 'map[[empty]]'] with root cause
     javax.persistence.TransactionRequiredException: No transactional EntityManager available
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:275)
    at com.sun.proxy.$Proxy51.merge(Unknown Source)
    at org.jasig.cas.ticket.registry.JpaTicketRegistry.updateTicket(JpaTicketRegistry.java:57)
    at org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry$TicketDelegator.updateTicket(AbstractDistributedTicketRegistry.java:101)
    at org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry$TicketGrantingTicketDelegator.grantServiceTicket(AbstractDistributedTicketRegistry.java:234)
    at org.jasig.cas.CentralAuthenticationServiceImpl.grantServiceTicket(CentralAuthenticationServiceImpl.java:313)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:

CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

以上的錯誤主要是因為CentralAuthenticationService.grantServiceTicket沒有transaction,我們需要修改ticketRegistry.xml的配置檔案

<tx:advice id="txRegistryAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="deleteTicket" read-only="false" />
        <tx:method name="addTicket" read-only="false" />
        <tx:method name="updateTicket" read-only="false" />
        <tx:method name="getTicket" read-only="true" />
        <tx:method name="getTickets" read-only="true" />
        <tx:method name="add*" read-only="false"/>
        <tx:method name="delete*" read-only="false"/>
        <tx:method name="save*" read-only="false"/>
        <tx:method name="update*" read-only="false"/>
        <tx:method name="get*" read-only="true"/>
        <tx:method name="grant*" read-only="false"/>
        <tx:method name="validate*" read-only="true"/>
        <tx:method name="sessionCount" read-only="true" />
        <tx:method name="serviceTicketCount" read-only="true" />
    </tx:attributes>
</tx:advice>

<tx:advice id="txRegistryLockingAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="getOwner" read-only="true" />
        <tx:method name="acquire" read-only="false" />
        <tx:method name="release" read-only="false" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="ticketRegistryOperations" expression="execution(* org.jasig.cas.ticket.registry.JpaTicketRegistry.*(..))"/>
    <aop:pointcut id="centralAuthenticationServiceOperations" expression="execution(* org.jasig.cas.CentralAuthenticationService.*(..))"/>
    <aop:pointcut id="ticketRegistryLockingOperations" expression="execution(* org.jasig.cas.ticket.registry.support.JpaLockingStrategy.*(..))"/>
    <!-- -->
    <aop:advisor advice-ref="txRegistryAdvice" pointcut-ref="ticketRegistryOperations"/>       
    <aop:advisor advice-ref="txRegistryAdvice" pointcut-ref="centralAuthenticationServiceOperations"/>
    <aop:advisor advice-ref="txRegistryLockingAdvice" pointcut-ref="ticketRegistryLockingOperations"/>
</aop:config>

錯誤

  • persistence manager沒有配置好或缺少依賴的jar

      18-Dec-2015 08:47:50.459 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring-configuration/ticketRegistry.xml]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1572)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
      at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:960)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:749)

*注意: 此處請要按照錯誤提示再META-INF下增加persistence.xml檔案,否則可能會出現衝突的情況。

  • 請用“SimpleTriggerFactoryBean”而非某些論壇裡面使用的“org.springframework.scheduling.quartz.SimpleTriggerBean”(這可能是老版本配置),正確配置如下:

      <bean id="periodicTicketRegistryCleanerTrigger"
          class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"
          p:jobDetail-ref="ticketRegistryCleanerJobDetail"
          p:startDelay="20000"
          p:repeatInterval="5000000"  />
  • 為DefaultTicketRegistryCleaner加上centralAuthenticationService

    老版本的DefaultTicketRegistryCleaner無需centralAuthenticationService,如果4.1.x沒有加上這個會出現錯誤:

      18-Dec-2015 08:55:43.357 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ticketRegistryCleaner' defined in ServletContext resource [/WEB-INF/spring-configuration/ticketRegistry.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner.<init>()
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1099)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1044)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)

    正確配置如下:

      <bean id="ticketRegistryCleaner" class="org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner"
      c:centralAuthenticationService-ref="centralAuthenticationService"
      c:ticketRegistry-ref="ticketRegistry"
      p:lock-ref="cleanerLock"
      />
  • 請使用較高版本的com.mchange.v2.c3p0

    否則會出現以下錯誤:

      18-Dec-2015 09:17:49.725 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
       org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring-configuration/ticketRegistry.xml]: Cannot resolve reference to bean 'ticketDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ticketDataSource' defined in ServletContext resource [/WEB-INF/spring-configuration/ticketRegistry.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'url' of bean class [com.mchange.v2.c3p0.ComboPooledDataSource]: Bean property 'url' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
      at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
      at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1475)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1220)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)

    正確的依賴:

      <dependency>
          <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.1</version>
      </dependency>
      <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>mchange-commons-java</artifactId>
        <version>0.2.10</version>
      </dependency>
  • 為host.name指定合適的引數(如:sso.hoau.com)

      2015-12-18 13:46:08,752 DEBUG [org.jasig.cas.web.support.CookieRetrievingCookieGenerator] - org.jose4j.lang.JoseException: A JWS Compact Serialization must have exactly 3 parts separated by period ('.') characters
      java.lang.RuntimeException: org.jose4j.lang.JoseException: A JWS Compact Serialization must have exactly 3 parts separated by period ('.') characters
      at org.jasig.cas.util.DefaultCipherExecutor.verifySignature(DefaultCipherExecutor.java:209)
      at org.jasig.cas.util.DefaultCipherExecutor.decode(DefaultCipherExecutor.java:107)
      at org.jasig.cas.web.support.DefaultCasCookieValueManager.obtainCookieValue(DefaultCasCookieValueManager.java:89)
      at org.jasig.cas.web.support.CookieRetrievingCookieGenerator.retrieveCookieValue(CookieRetrievingCookieGenerator.java:116)
  • Cannot subclass final class class org.jasig.cas.ticket.registry.JpaTicketRegistry

    如果參照網上某些解決方案,試圖新增tx:annotation-driven

      <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

    會出現如下錯誤

      Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.jasig.cas.ticket.registry.JpaTicketRegistry]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class org.jasig.cas.ticket.registry.JpaTicketRegistry
      at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
      at  org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
  • 4.1.2的bug

    由於以下或可能遇到的更多錯誤,mmoayyed建議將overlay升到4.1.3

    在登陸時碰到後臺錯誤“java.lang.NullPointerException
    at org.jasig.cas.ticket.support.TicketGrantingTicketExpirationPolicy.isExpired”

      18-Dec-2015 17:35:00.194 SEVERE [http-nio-8443-exec-8] 
      org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [cas] in context with path [/cas] threw exception [Request processing failed; 
      nested exception is 
      org.springframework.webflow.execution.ActionExecutionException: Exception thrown executing 
      org.jasig.cas.web.flow.TicketGrantingTicketCheckAction@313fe175 in state 'ticketGrantingTicketCheck' of flow 'login' -- action 
      execution attributes were 'map[[empty]]'] with root cause
      java.lang.NullPointerException
          at org.jasig.cas.ticket.support.TicketGrantingTicketExpirationPolicy.isExpired(TicketGrantingTicketExpirationPolicy.java:131)
          at org.jasig.cas.ticket.AbstractTicket.isExpired(AbstractTicket.java:158)
          at org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry$TicketDelegator.isExpired(AbstractDistributedTicketRegistry.java:115)
          at org.jasig.cas.CentralAuthenticationServiceImpl.getTicket(CentralAuthenticationServiceImpl.java:525)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:497)
          at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
          at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)

https://github.com/Jasig/cas/issues/1323
CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

https://github.com/Jasig/cas/issues/1367
CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服務端)

測試

此處略去,請自行驗證。

結束

相關文章