Yale CAS as an Acegi Client in SpringSide
First, Set SpringSide's web.xml, we use Acegi CAS Filter:
<
filter-mapping
>
< filter-name > hibernateFilter </ filter-name >
< url-pattern > /j_acegi_cas_security_check </ url-pattern >
</ filter-mapping >
< filter-name > hibernateFilter </ filter-name >
< url-pattern > /j_acegi_cas_security_check </ url-pattern >
</ filter-mapping >
We Should Set Main ACEGI application Context:
1) filterChainProxy should add a cas filter as Acegi's Sample, but here, we reuse
authenticationProcessingFilter, which we act as cas client filter.
<
bean
id
="filterChainProxy"
class ="org.acegisecurity.util.FilterChainProxy" >
< property name ="filterInvocationDefinitionSource" >
< value >
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,anonymousProcessingFilter,authenticationProcessingFilter,rememberMeProcessingFilter,logoutFilter,channelProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
</ value >
</ property >
</ bean >
class ="org.acegisecurity.util.FilterChainProxy" >
< property name ="filterInvocationDefinitionSource" >
< value >
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,anonymousProcessingFilter,authenticationProcessingFilter,rememberMeProcessingFilter,logoutFilter,channelProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
</ value >
</ property >
</ bean >
2) authenticationProcessingFilter, of course, play the most important role in this
applicationContext_acegi.xml.
In SpringSide, /admin is protected resource, so defaultTargetUrl protected it
and all those request to the target url must be authenticated by authenticationManager.
3) Then, we set all the needed beans in CAS Filter
<!--
========= Acegi as a CAS Client的配置=============
-->
< bean id ="exceptionTranslationFilter" class ="org.acegisecurity.ui.ExceptionTranslationFilter" >
< property name ="authenticationEntryPoint" >
< ref local ="casProcessingFilterEntryPoint" />
</ property >
</ bean >
<!-- cas config -->
< bean id ="casProcessingFilterEntryPoint" class ="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint" >
< property name ="loginUrl" >< value > https://sourcesite:8443/cas/login </ value ></ property >
< property name ="serviceProperties" >< ref local ="serviceProperties" /></ property >
</ bean >
< bean id ="authenticationManager" class ="org.acegisecurity.providers.ProviderManager" >
< property name ="providers" >
< list >
< ref local ="casAuthenticationProvider" />
</ list >
</ property >
</ bean >
< bean id ="casAuthenticationProvider" class ="org.acegisecurity.providers.cas.CasAuthenticationProvider" >
< property name ="casAuthoritiesPopulator" >< ref bean ="casAuthoritiesPopulator" /></ property >
< property name ="casProxyDecider" >< ref local ="casProxyDecider" /></ property >
< property name ="ticketValidator" >< ref local ="casProxyTicketValidator" /></ property >
< property name ="statelessTicketCache" >< ref local ="statelessTicketCache" /></ property >
< property name ="key" >< value > my_password_for_this_auth_provider_only </ value ></ property >
</ bean >
< bean id ="casProxyTicketValidator" class ="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator" >
< property name ="casValidate" >< value > https://sourcesite:8443/cas/proxyValidate </ value ></ property >
< property name ="serviceProperties" >< ref local ="serviceProperties" /></ property >
</ bean >
<!--
<bean id="casProxyDecider" class="org.acegisecurity.providers.cas.proxy.AcceptAnyCasProxy" />
-->
< bean id ="casProxyDecider" class ="org.acegisecurity.providers.cas.proxy.RejectProxyTickets" />
< bean id ="serviceProperties" class ="org.acegisecurity.ui.cas.ServiceProperties" >
< property name ="service" >
< value > http://gzug:8080/springside/j_acegi_cas_security_check </ value >
</ property >
< property name ="sendRenew" >
< value > false </ value >
</ property >
</ bean >
< bean id ="statelessTicketCache" class ="org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache" >
< property name ="cache" >
< bean class ="org.springframework.cache.ehcache.EhCacheFactoryBean" >
< property name ="cacheManager" >
< bean class ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
</ property >
< property name ="cacheName" value ="userCache" />
</ bean >
</ property >
</ bean >
< bean id ="casAuthoritiesPopulator" class ="org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator" >
< property name ="userDetailsService" >< ref local ="jdbcDaoImpl" /></ property >
</ bean >
< bean id ="casProcessingFilter" class ="org.acegisecurity.ui.cas.CasProcessingFilter" >
< property name ="authenticationManager" >< ref local ="authenticationManager" /></ property >
< property name ="authenticationFailureUrl" >< value > /casfailed.jsp </ value ></ property >
< property name ="defaultTargetUrl" >< value > / </ value ></ property >
< property name ="filterProcessesUrl" >< value > /j_acegi_cas_security_check </ value ></ property >
</ bean >
< bean id ="exceptionTranslationFilter" class ="org.acegisecurity.ui.ExceptionTranslationFilter" >
< property name ="authenticationEntryPoint" >
< ref local ="casProcessingFilterEntryPoint" />
</ property >
</ bean >
<!-- cas config -->
< bean id ="casProcessingFilterEntryPoint" class ="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint" >
< property name ="loginUrl" >< value > https://sourcesite:8443/cas/login </ value ></ property >
< property name ="serviceProperties" >< ref local ="serviceProperties" /></ property >
</ bean >
< bean id ="authenticationManager" class ="org.acegisecurity.providers.ProviderManager" >
< property name ="providers" >
< list >
< ref local ="casAuthenticationProvider" />
</ list >
</ property >
</ bean >
< bean id ="casAuthenticationProvider" class ="org.acegisecurity.providers.cas.CasAuthenticationProvider" >
< property name ="casAuthoritiesPopulator" >< ref bean ="casAuthoritiesPopulator" /></ property >
< property name ="casProxyDecider" >< ref local ="casProxyDecider" /></ property >
< property name ="ticketValidator" >< ref local ="casProxyTicketValidator" /></ property >
< property name ="statelessTicketCache" >< ref local ="statelessTicketCache" /></ property >
< property name ="key" >< value > my_password_for_this_auth_provider_only </ value ></ property >
</ bean >
< bean id ="casProxyTicketValidator" class ="org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator" >
< property name ="casValidate" >< value > https://sourcesite:8443/cas/proxyValidate </ value ></ property >
< property name ="serviceProperties" >< ref local ="serviceProperties" /></ property >
</ bean >
<!--
<bean id="casProxyDecider" class="org.acegisecurity.providers.cas.proxy.AcceptAnyCasProxy" />
-->
< bean id ="casProxyDecider" class ="org.acegisecurity.providers.cas.proxy.RejectProxyTickets" />
< bean id ="serviceProperties" class ="org.acegisecurity.ui.cas.ServiceProperties" >
< property name ="service" >
< value > http://gzug:8080/springside/j_acegi_cas_security_check </ value >
</ property >
< property name ="sendRenew" >
< value > false </ value >
</ property >
</ bean >
< bean id ="statelessTicketCache" class ="org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache" >
< property name ="cache" >
< bean class ="org.springframework.cache.ehcache.EhCacheFactoryBean" >
< property name ="cacheManager" >
< bean class ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
</ property >
< property name ="cacheName" value ="userCache" />
</ bean >
</ property >
</ bean >
< bean id ="casAuthoritiesPopulator" class ="org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator" >
< property name ="userDetailsService" >< ref local ="jdbcDaoImpl" /></ property >
</ bean >
< bean id ="casProcessingFilter" class ="org.acegisecurity.ui.cas.CasProcessingFilter" >
< property name ="authenticationManager" >< ref local ="authenticationManager" /></ property >
< property name ="authenticationFailureUrl" >< value > /casfailed.jsp </ value ></ property >
< property name ="defaultTargetUrl" >< value > / </ value ></ property >
< property name ="filterProcessesUrl" >< value > /j_acegi_cas_security_check </ value ></ property >
</ bean >
casProcessingFilterEntryPoint is very critical,
loginUrl is the CAS Server's /login url, you should set up your CAS Server(2.0 or 3.0) and config for
those JKS keystore after enable SSL in Tomcat(Tomcat 5.5/conf/server.xml) and place the cacerts that
have the CAS Server's public cert to Acegi Client's JDK/jre/lib/security/
Check serviceProperties to make sure that SpringSide Service url is config as /j_acegi_cas_security_check
because Yale CAS use ticket cache for SSO impl, so we should config for statelessTicketCache
Just use springframework's ehcache for cacheManager.
SpringSide use jdbcDaoImpl which perform database authentication. So I am very happy to use it
as casAuthoritiesPopulator , which will set use detail for the user. And these info are very useful for
application authorization.
<
bean
id
="jdbcDaoImpl"
class ="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl" >
< property name ="dataSource" ref ="dataSource" />
< property name ="usersByUsernameQuery" >
< value >
select loginid,passwd,1 from ss_users where status='1' and loginid = ?
</ value >
</ property >
< property name ="authoritiesByUsernameQuery" >
< value >
select u.loginid,p.name from ss_users u,ss_roles r,ss_permissions
p,ss_user_role ur,ss_role_permis rp where u.id=ur.user_id and
r.id=ur.role_id and p.id=rp.permis_id and
r.id=rp.role_id and p.status='1' and u.loginid=?
</ value >
</ property >
</ bean >
class ="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl" >
< property name ="dataSource" ref ="dataSource" />
< property name ="usersByUsernameQuery" >
< value >
select loginid,passwd,1 from ss_users where status='1' and loginid = ?
</ value >
</ property >
< property name ="authoritiesByUsernameQuery" >
< value >
select u.loginid,p.name from ss_users u,ss_roles r,ss_permissions
p,ss_user_role ur,ss_role_permis rp where u.id=ur.user_id and
r.id=ur.role_id and p.id=rp.permis_id and
r.id=rp.role_id and p.status='1' and u.loginid=?
</ value >
</ property >
</ bean >
There is little difference between casclient 2.0.12 and Acegi, right?
Note that in my env, gzug:8080/springside is bookstore webapp
and sourcesite:8443 is the CAS 3 Server.
Hope for suggestion.....