參考:http://elim.iteye.com/blog/2270446web
衆所周知,Cas是對單點登陸的一種實現。本文假設讀者已經瞭解了Cas的原理及其使用,這些內容在本文將不會討論。Cas有Server端和Client端,Client端一般對應着咱們本身的應用,Spring Security整合Cas指的就是在Spring Security應用中整合Cas Client,已達到使用Cas Server實現單點登陸和登出的效果。本文旨在描述如何在Spring Security應用中使用Cas的單點登陸。spring
首先須要將Spring Security對Cas支持的jar包加入到應用的類路徑中。若是咱們的應用使用Maven構造的,則能夠在應用的pom.xml文件中加上以下依賴。緩存
<dependency>session
<groupId>org.springframework.security</groupId>app
<artifactId>spring-security-cas</artifactId>less
<version>${spring.security.version}</version>jsp
</dependency>ide
加入了spring-security-cas-xxx.jar到Spring Security應用的classpath後,咱們即可以開始配置咱們的Spring Security應用使用Cas進行單點登陸了。編碼
首先須要作的是將應用的登陸認證入口改成使用CasAuthenticationEntryPoint。因此首先咱們須要配置一個CasAuthenticationEntryPoint對應的bean,而後指定須要進行登陸認證時使用該AuthenticationEntryPoint。配置CasAuthenticationEntryPoint時須要指定一個ServiceProperties,該對象主要用來描述service(Cas概念)相關的屬性,主要是指定在Cas Server認證成功後將要跳轉的地址。url
<!-- 指定登陸入口爲casEntryPoint -->
<security:http entry-point-ref="casEntryPoint">
...
</security:http>
<!-- 認證的入口 -->
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<!-- Cas Server的登陸地址,elim是個人計算機名 -->
<property name="loginUrl" value="https://elim:8443/cas/login" />
<!-- service相關的屬性 -->
<property name="serviceProperties" ref="serviceProperties" />
</bean>
<!-- 指定service相關信息 -->
<bean id="serviceProperties"class="org.springframework.security.cas.ServiceProperties">
<!-- Cas Server認證成功後的跳轉地址,這裏要跳轉到咱們的Spring Security應用,以後會由CasAuthenticationFilter處理,默認處理地址爲/j_spring_cas_security_check -->
<property name="service"
value="http://elim:8080/app/j_spring_cas_security_check" />
</bean>
以後咱們須要配置一個CasAuthenticationFilter,並將其放置在Filter鏈表中CAS_FILTER的位置,以處理Cas Server認證成功後的頁面跳轉,用以在Spring Security中進行認證。該Filter會將Cas Server傳遞過來的ticket(Cas概念)封裝成一個Authentication(對應UsernamePasswordAuthenticationToken,其中ticket做爲該Authentication的password),而後傳遞給AuthenticationManager進行認證。
<security:http entry-point-ref="casEntryPoint">
...
<security:custom-filter ref="casFilter" position="CAS_FILTER"/>
...
</security:http>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 指定處理地址,不指定時默認將會是「/j_spring_cas_security_check」 -->
<property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
</bean>
CasAuthenticationFilter會將封裝好的包含Cas Server傳遞過來的ticket的Authentication對象傳遞給AuthenticationManager進行認證。咱們知道默認的AuthenticationManager實現類爲ProviderManager,而ProviderManager中真正進行認證的是AuthenticationProvider。因此接下來咱們要在AuthenticationManager中配置一個可以處理CasAuthenticationFilter傳遞過來的Authentication對象的AuthenticationProvider實現,CasAuthenticationProvider。CasAuthenticationProvider首先會利用TicketValidator(Cas概念)對Authentication中包含的ticket信息進行認證。認證經過後將利用持有的AuthenticationUserDetailsService根據認證經過後回傳的Assertion對象中擁有的username加載用戶對應的UserDetails,即主要是加載用戶的相關權限信息GrantedAuthority。而後構造一個CasAuthenticationToken進行返回。以後的邏輯就是正常的Spring Security的邏輯了。
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider"/>
</security:authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- 經過username來加載UserDetails -->
<property name="authenticationUserDetailsService">
<beanclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<!-- 真正加載UserDetails的UserDetailsService實現 -->
<constructor-arg ref="userDetailsService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<!-- 配置TicketValidator在登陸認證成功後驗證ticket -->
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<!-- Cas Server訪問地址的前綴,即根路徑-->
<constructor-arg index="0" value="https:// elim:8443/cas" />
</bean>
</property>
<property name="key" value="key4CasAuthenticationProvider" />
</bean>
<bean id="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
通過以上三步配置之後,咱們的Spring Security應用就已經跟Cas整合好了,能夠在須要登陸的時候經過Cas Server進行單點登陸了。
Spring Security應用整合Cas Client配置單點登出功能實際和單獨使用Cas Client配置單點登出功能同樣,其根本都是經過配置一個SingleSignOutFilter響應Cas Server單點登出時的回調,配置一個SingleSignOutHttpSessionListener用於在Session過時時刪除SingleSignOutFilter存放的對應信息。SingleSignOutFilter須要配置在Cas 的AuthenticationFilter以前,對於Spring Security應用而言,該Filter一般是配置在Spring Security的配置文件中,並且是配置在CAS_FILTER以前。因此咱們能夠在Spring Security的配置文件中進行以下配置。
<security:http entry-point-ref="casEntryPoint">
<!-- SingleSignOutFilter放在CAS_FILTER以前 -->
<security:custom-filter ref="casLogoutFilter" before="CAS_FILTER"/>
<security:custom-filter ref="casFilter" position="CAS_FILTER"/>
...
</security:http>
<bean id="casLogoutFilter"class="org.jasig.cas.client.session.SingleSignOutFilter"/>
而後跟單獨使用Cas Client同樣,在web.xml文件中配置一個SingleSignOutHttpSessionListener。
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
通過以上配置在訪問Cas Server的logout地址(如:https:elim:8443/cas/logout)進行登出時,Cas Server登出後將回調其中註冊的每個Service(Cas概念,即client應用),此時在client應用中配置好的SingleSignOutFilter將處理對應Client應用的登出操做。
雖然以上配置能夠知足咱們在Spring Security應用中的單點登出要求,但Cas官方文檔和Spring Security官方文檔都推薦咱們在Cas Client應用進行登出操做時,不是直接訪問Cas Server的logout,而是先登出本應用,而後告訴用戶其當前登出的只是本應用,再提供一個對應Cas Server的連接,使其能夠進行真正的單點登出。對此,Spring Security官方文檔中給咱們提供例子是提供兩個LogoutFilter,一個是登出當前Spring Security應用,一個是登出Cas Server的。
<security:http entry-point-ref="casEntryPoint">
<!-- 請求登出Cas Server的過濾器,放在Spring Security的登出過濾器以前 -->
<security:custom-filter ref="requestCasLogoutFilter" before="LOGOUT_FILTER"/>
<!-- SingleSignOutFilter放在CAS_FILTER以前 -->
<security:custom-filter ref="casLogoutFilter" before="CAS_FILTER"/>
<security:custom-filter ref="casFilter" position="CAS_FILTER"/>
...
</security:http>
<bean id="requestCasLogoutFilter"class="org.springframework.security.web.authentication.logout.LogoutFilter">
<!-- 指定登出成功後須要跳轉的地址,這裏指向Cas Server的登出URL,以實現單點登出 -->
<constructor-arg value="https://elim:8443/cas/logout"/>
<constructor-arg>
<beanclass="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<!-- 該Filter須要處理的地址,默認是Spring Security的默認登出地址「/j_spring_security_logout」-->
<property name="filterProcessesUrl" value="/j_spring_cas_security_logout"/>
</bean>
此外,Spring Security推薦咱們在使用Cas Server的單點登出時一塊兒使用CharacterEncodingFilter,以免SingleSignOutFilter在獲取參數時出現編碼問題。
關於Cas應用使用代理的基本原理、概念等內容的介紹不在本文討論範圍以內,如需瞭解請讀者參考其它資料,或者參考個人另外一篇博文。本文旨在描述Spring Security應用在整合Cas後如何經過Cas Proxy訪問另外一個受Cas包含的應用。
使用Cas Proxy時有兩個主體,代理端和被代理端。並且咱們知道代理端和被代理端針對Cas20ProxyReceivingTicketValidationFilter的配置是不同的,雖然整合Cas的Spring Security應用再也不使用Cas20ProxyReceivingTicketValidationFilter了,但其底層的核心機制是同樣的。因此Cas整合Spring Security後的應用在做爲代理端和被代理端時的配置也是不同的。接下來將分開講解Spring Security應用做爲代理端和被代理端整合Cas後的配置。
首先須要爲CasAuthenticationFilter多指定兩個參數,proxyReceptorUrl和proxyGrantingTicketStorage。proxyReceptorUrl用以指定Cas Server在回調代理端傳遞pgtId和pgtIou時回調地址相對於代理端的路徑,如「/proxyCallback」,CasAuthenticationFilter會根據proxyReceptorUrl來肯定一個請求是否來自Cas Server針對proxy的回調。若是是則須要接收Cas Server傳遞過來的pgtId和pgtIou,並將它們保存在持有的ProxyGrantingTicketStorage中。CasAuthenticationProvider以後會從ProxyGrantingTicketStorage中獲取對應的pgtId,即proxy granting ticket,並將其保存在AttributePrincipal中,而AttributePrincipal又會保存到對應的Assertion中。
<!-- 配置ProxyGrantingTicketStorage,用以保存pgtId和pgtIou -->
<bean id="proxyGrantingTicketStorage"class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 指定處理地址,不指定時默認將會是「/j_spring_cas_security_check」 -->
<property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage"/>
<property name="proxyReceptorUrl" value="/proxyCallback"/>
</bean>
其次是須要將CasAuthenticationProvider持有的TicketValidator由Cas20ServiceTicketValidator改爲Cas20ProxyTicketValidator。其須要配置一個ProxyGrantingTicketStorage用來獲取proxy granting ticket,即咱們熟知的pgtId。在單獨使用Cas Proxy時,Cas20ProxyReceivingTicketValidationFilter內部默認持有一個ProxyGrantingTicketStorage實現,其使用的Cas20ProxyTicketValidator也將使用該ProxyGrantingTicketStorage。整合Spring Security以後, Spring Security不使用Cas20ProxyReceivingTicketValidationFilter,而直接由CasAuthenticationFilter獲取proxy granting ticket,由CasAuthenticationProvider對ticket進行校驗。Cas20ProxyTicketValidator內部沒默認的ProxyGrantingTicketStorage,因此在配置Cas20ProxyTicketValidator時咱們須要給其指定一個ProxyGrantingTicketStorage實現。此外還須要爲Cas20ProxyTicketValidator指定一個proxyCallbackUrl用以指定在Cas20ProxyTicketValidator經過Cas Server校驗service ticket成功後將回調哪一個地址以傳遞pgtId和pgtIou。proxyCallbackUrl默認狀況下必須使用https協議,而應用的其它請求能夠用非https協議。其它的配置和Cas20ServiceTicketValidator同樣,Cas20ProxyTicketValidator的父類其實就是Cas20ServiceTicketValidator。
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- 經過username來加載UserDetails -->
<property name="authenticationUserDetailsService">
<beanclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<!-- 真正加載UserDetails的UserDetailsService實現 -->
<constructor-arg ref="userDetailsService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<!-- 配置TicketValidator在登陸認證成功後驗證ticket -->
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<!-- Cas Server訪問地址的前綴,即根路徑-->
<constructor-arg index="0" value="https://elim:8443/cas" />
<!-- 指定Cas Server回調傳遞pgtId和pgtIou的地址,該地址必須使用https協議 -->
<property name="proxyCallbackUrl"value="https://elim:8043/app/proxyCallback"/>
<property name="proxyGrantingTicketStorage"ref="proxyGrantingTicketStorage"/>
</bean>
</property>
<property name="key" value="key4CasAuthenticationProvider" />
</bean>
通過以上步驟後咱們整合Cas後的Spring Security應用就能夠做爲代理端使用Cas proxy訪問其它被Cas保護的應用了,固然前提是其它被代理端可以接受咱們應用的代理,瞭解Cas Proxy的人應該都知道這一點,在接下來的Spring Security應用整合Cas做爲被代理端中也會講到這部份內容。這裏咱們假設如今有一個應用app2可以接受咱們應用的代理訪問,那麼在基於上述配置的應用中咱們能夠經過以下代碼訪問app2。
@Controller
@RequestMapping("/cas/test")
publicclass CasTestController {
@RequestMapping("/getData")
publicvoid getDataFromApp(PrintWriter writer) throws Exception {
//一、從SecurityContextHolder獲取到當前的Authentication對象,其是一個CasAuthenticationToken
CasAuthenticationToken cat = (CasAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
//二、獲取到AttributePrincipal對象
AttributePrincipal principal = cat.getAssertion().getPrincipal();
//三、獲取對應的proxy ticket
String proxyTicket = principal.getProxyTicketFor("http://elim:8081/app2/getData.jsp");
//四、請求被代理應用時將獲取到的proxy ticket以參數ticket進行傳遞
URL url = new URL("http://elim:8081/app2/getData.jsp?ticket=" + URLEncoder.encode(proxyTicket, "UTF-8"));
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
StringBuffer content = new StringBuffer();
String line = null;
while ((line=br.readLine()) != null) {
content.append(line).append("<br/>");
}
writer.write(content.toString());
}
}
須要注意的是經過AttributePrincipal的getProxyTicketFor()方法獲取proxy ticket時,每調用一次都會獲取一個全新的proxy ticket。用戶能夠根據本身的須要將獲取到的proxy ticket按照指定的URL緩存起來,以免每次都去針對同一個URL獲取一個全新的proxy ticket。此外,若是在被代理端認證時根據proxy ticket緩存了Authentication的話也須要咱們在代理端保證針對同一URL傳遞過去的proxy ticket是同樣的,不然被代理端針對proxy ticket緩存Authentication的功能就沒用了。
Spring Security應用整合Cas使用Cas Proxy做爲被代理端時主要須要進行三點修改。
第一點是經過ServiceProperties指定CasAuthenticationFilter的authenticateAllArtifacts爲true,這樣CasAuthenticationFilter將會嘗試對全部ticket進行認證,而不是隻認證來自filterProccessUrl指定地址的請求。這樣代理端在請求被代理端的資源時將proxy ticket以參數ticket進行傳遞時,CasAuthenticationFilter纔會讓CasAuthenticationProvider對proxy ticket進行校驗,這樣咱們的請求才有可能被CasAuthenticationProvider認證成功並請求到真正的資源。
第二點是指定CasAuthenticationFilter使用的AuthenticationDetailsSource爲ServiceAuthenticationDetailsSource。CasAuthenticationFilter默認使用的是WebAuthenticationDetailsSource。ServiceAuthenticationDetailsSource將構建一個ServiceAuthenticationDetails對象做爲當前Authentication的details對象。ServiceAuthenticationDetailsSource構建的ServiceAuthenticationDetails對象會將當前請求的地址構建爲一個serviceUrl,經過其getServiceUrl()方法能夠獲取到該serviceUrl地址。以後該Authentication對象傳遞到CasAuthenticationProvider進行認證時就能夠從Authentication的details中獲取到對應的serviceUrl,並在經過Cas Server對代理端以參數ticket傳遞過來的proxy ticket進行驗證時連同對應的serviceUrl一塊兒傳遞過去。由於以前代理端申請proxy ticket時就是經過該serviceUrl進行申請的,Cas Server須要對於它們的配對來驗證對應的proxy ticket是否有效。
第三點是將CasAuthenticationProvider的TicketValidator由Cas20ServiceTicketValidator改成Cas20ProxyTicketValidator,由於Cas Proxy被代理端須要調用Cas Server的proxyValidator對代理端傳遞過來的proxy ticket進行驗證。此外須要經過acceptAnyProxy或allowedProxyChains指定將接受哪些代理。acceptAnyProxy用以指定是否接受全部的代理,可選值爲true或false。allowedProxyChains則用以指定具體接受哪些代理,其對應的值是代理端在獲取pgtId時提供給Cas Server的回調地址,如咱們須要接受前面示例中代理端的代理,則咱們的allowedProxyChains的值應該是「https://elim:8043/app/proxyCallback」。若是須要接受多個代理端的代理,則在指定allowedProxyChains時多個代理端回調地址應各佔一行。
針對以上三點,咱們的Spring Security應用整合Cas做爲Cas Proxy的被代理端時須要對咱們的配置進行以下改造。
<!-- 指定service相關信息 -->
<bean id="serviceProperties"class="org.springframework.security.cas.ServiceProperties">
<!-- Cas Server認證成功後的跳轉地址,這裏要跳轉到咱們的Spring Security應用,以後會由CasAuthenticationFilter處理,默認處理地址爲/j_spring_cas_security_check -->
<property name="service"
value="http://elim:8083/app2/j_spring_cas_security_check" />
<!-- 經過ServiceProperties指定CasAuthenticationFilter的authenticateAllArtifacts爲true -->
<property name="authenticateAllArtifacts" value="true"/>
</bean>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 指定處理地址,不指定時默認將會是「/j_spring_cas_security_check」 -->
<property name="filterProcessesUrl" value="/j_spring_cas_security_check" />
<!-- 經過ServiceProperties指定CasAuthenticationFilter的authenticateAllArtifacts爲true -->
<property name="serviceProperties" ref="serviceProperties" />
<!-- 指定使用的AuthenticationDetailsSource爲ServiceAuthenticationDetailsSource -->
<property name="authenticationDetailsSource">
<beanclass="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
</property>
</bean>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- 經過username來加載UserDetails -->
<property name="authenticationUserDetailsService">
<beanclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<!-- 真正加載UserDetails的UserDetailsService實現 -->
<constructor-arg ref="userDetailsService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<!-- 配置TicketValidator在登陸認證成功後驗證ticket -->
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<!-- Cas Server訪問地址的前綴,即根路徑-->
<constructor-arg index="0" value="https://elim:8443/cas" />
<property name="allowedProxyChains">
<value>https://elim:8043/app/proxyCallback</value>
</property>
</bean>
</property>
<property name="key" value="key4CasAuthenticationProvider" />
</bean>
此外,對於被代理端而言,代理端在對其進行訪問時都被認爲是無狀態的。對於無狀態的認證CasAuthenticationProvider將在認證成功後將對應的Authentication對象以proxy tickit爲key存放到所持有的StatelessTicketCache中,而後在下次代理端訪問時將優先根據代理端傳遞過來的proxy ticket從StatelessTicketCache中獲取Authentication對象,若是存在則再也不進行認證,不然將繼續進行認證。CasAuthenticationProvider默認持有的StatelessTicketCache爲NullStatelessTicketCache,其全部的實現都是空的。因此默認狀況下,被代理端在被代理端訪問時將每次都對代理端進行認證。若是用戶不但願在被代理端每次都對代理端的請求進行認證,則能夠爲被代理端的CasAuthenticationProvider指定一個StatelessTicketCache。用戶能夠實現本身的StatelessTicketCache,並指定CasAuthenticationProvider使用的StatelessTicketCache爲該StatelessTicketCache。不過也可使用Spring Security爲咱們提供的EhCacheBasedTicketCache。EhCacheBasedTicketCache是基於Ehcache實現的一個StatelessTicketCache。如下是一個爲CasAuthenticationProvider配置EhCacheBasedTicketCache的示例。
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
……
<property name="statelessTicketCache">
<beanclass="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
<!-- Ehcache對象 -->
<property name="cache" ref="proxyTicketCache"/>
</bean>
</property>
……
</bean>
<!-- 定義一個Ehcache -->
<bean id="proxyTicketCache"class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheName" value="proxyTicketCache" />
<property name="timeToLive" value="600"/>
</bean>
須要注意的是在代理端經過AttributePrincipal的getProxyTicketFor()方法獲取到的proxy ticket每次都是不同的,因此在被代理端經過StatelessTicketCache根據proxy ticket緩存認證對象Authentication時只有在同一proxy ticket可以請求屢次的狀況下才會有用,這也就要求咱們在代理端一樣能將proxy ticket緩存起來,以在請求同一地址時能使用相同的proxy ticket。
Cas Proxy的代理端和被代理端是相互獨立的,因此一個Cas應用既能夠做爲代理端去訪問其它Cas應用,也能夠做爲被代理端被其它應用訪問。當Spring Security應用整合Cas後既想做爲Cas Proxy的代理端訪問其它Cas應用,也想做爲被代理端被其它Cas應用訪問時只須要將上述做爲代理端的配置和做爲被代理端的配置整到一塊兒就好了。如下是一段示例代碼。
<!-- 指定service相關信息 -->
<bean id="serviceProperties"class="org.springframework.security.cas.ServiceProperties">
<!-- Cas Server認證成功後的跳轉地址,這裏要跳轉到咱們的Spring Security應用,以後會由CasAuthenticationFilter處理,默認處理地址爲/j_spring_cas_security_check -->
<property name="service"
value="http://elim:8080/app /j_spring_cas_security_check" />
<property name="authenticateAllArtifacts" value="true"/>
</bean>
<!-- 配置ProxyGrantingTicketStorage,用以保存pgtId和pgtIou -->
<bean id="proxyGrantingTicketStorage"class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 指定處理地址,不指定時默認將會是「/j_spring_cas_security_check」 -->
<property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage"/>
<property name="proxyReceptorUrl" value="/proxyCallback"/>
<!-- 經過ServiceProperties指定CasAuthenticationFilter的authenticateAllArtifacts爲true -->
<property name="serviceProperties" ref="serviceProperties" />
<!-- 指定使用的AuthenticationDetailsSource爲ServiceAuthenticationDetailsSource -->
<property name="authenticationDetailsSource">
<beanclass="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
</property>
</bean>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- 經過username來加載UserDetails -->
<property name="authenticationUserDetailsService">
<beanclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<!-- 真正加載UserDetails的UserDetailsService實現 -->
<constructor-arg ref="userDetailsService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<!-- 配置TicketValidator在登陸認證成功後驗證ticket -->
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<!-- Cas Server訪問地址的前綴,即根路徑-->
<constructor-arg index="0" value="https://elim:8443/cas" />
<!-- 指定Cas Server回調傳遞pgtId和pgtIou的地址,該地址必須使用https協議 -->
<property name="proxyCallbackUrl"value="https://elim:8043/app/proxyCallback"/>
<property name="proxyGrantingTicketStorage"ref="proxyGrantingTicketStorage"/>
<!-- 做爲被代理端時配置接收任何代理 -->
<property name="acceptAnyProxy" value="true"/>
</bean>
</property>
<property name="key" value="key4CasAuthenticationProvider" />
</bean>