Skip navigation.
Home

How Spring Security hooks to Central Authentication Service (CAS)

CAS High Level Collaboration DiagramOur latest software project used CAS for authentication and single sign-on. I couldn't find any good documentation on how Spring Security and CAS played together. There is some documentation about how to configure your application to use CAS but not much on what messages go back and forth by whom and when.

Normally, we would drop in the CAS war, do a little configuration and use it for single sign-on for a suite of applications. I had a basic understanding of how it worked conceptually, but not really a complete understanding of how it worked in practice. This was okay provided that we didn't run into any issues with authentication or needed to extend CAS functionality.

This understanding gap started to show up when I needed to use Spring Security as the CAS client. I was able able to configure the client easily enough, but couldn't quite get my head around how Spring Security interacted with CAS at a message level. I put together the following diagrams to address that gap.

High Level Collaboration Diagram

This diagram doesn't show the internals of the Spring Security client but it is very helpful if you aren't all that familiar with how CAS works in general. The main takeaways are how involved the browser is in the process. There are a bunch of redirects that happen (really without the user noticing) during an login/authentication. The second thing is step #8. This is the only time where the Application (Spring Security client) talks directly to CAS. This is also why the Application's JVM needs to be accept the SSL certificate of the CAS application. This seems to trip people up.

CAS High Level Collaboration Diagram

Sequence Diagram

This diagram has the three main actors in the Spring Security CAS client and shows which classes actually initiate redirects. This is very helpful if you need to modify the CAS application. I put it together as a first step in determining how to add password expiration detection with force password change into CAS instead of having them in each application.

CAS Sequence Diagram

Matt Fleming's picture

Non-Simple security.xml

This is the real security.xml file that we use to configure Spring Security. Normally we wouldn't need to do this expanded version, but I wanted the channelProcessingFilter to fire (which switches the protocol from http to https) on all non-secured resources. If the concise configuration actually used the filters attribute on the sec:intercept-url element, I wouldn't have to break it all out. It was good to figure out anyway.

-Matt

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
 
    <bean id="securityFilter" class="org.springframework.security.util.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/images/**" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/css/**" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/js/**" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/403.jsp" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/404.jsp" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/error.jsp" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/**/cas/changePassword.htm*" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/**/cas/login.htm*" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/**/cas/passwordExpired.htm*" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/**/*.html*" filters="channelProcessingFilter"/>
            <sec:filter-chain pattern="/**"
                              filters="channelProcessingFilter,httpSessionContextIntegrationFilter,logoutFilter,casSingleSignOutFilter,casProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor"/>
        </sec:filter-chain-map>
    </bean>
 
    <!-- this is what hooks up the CAS entry point -->
    <bean id="exceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <ref local="casProcessingFilterEntryPoint"/>
        </property>
    </bean>
 
    <!-- where do I go when I need authentication from CAS-->
    <bean id="casProcessingFilterEntryPoint" class="org.springframework.security.ui.cas.CasProcessingFilterEntryPoint">
        <property name="loginUrl" value="https://localhost:5543/cas/login"/>
        <property name="serviceProperties" ref="serviceProperties"/>
    </bean>
 
    <!-- defines which roles are allowed to access http resources -->
    <bean id="filterInvocationInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager" ref="accessDecisionManager"/>
        <property name="objectDefinitionSource">
            <value>
                PATTERN_TYPE_APACHE_ANT
                **=ROLE_ALLOWED_ROLES_HERE
            </value>
        </property>
    </bean>
 
    <!-- hooks up CAS ticket validator and user details loader -->
    <bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="casAuthenticationProvider"/>
            </list>
        </property>
    </bean>
 
    <!-- supporting class for filterInvocationInterceptor -->
    <bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
        <property name="allowIfAllAbstainDecisions" value="false"/>
        <property name="decisionVoters">
            <list>
                <ref local="roleVoter"/>
            </list>
        </property>
    </bean>
 
    <bean id="roleVoter" class="org.springframework.security.vote.RoleVoter">
        <property name="rolePrefix" value=""/>
    </bean>
 
    <!-- setup method level security using annotations -->
    <sec:global-method-security jsr250-annotations="enabled" secured-annotations="enabled"/>
    <alias name="authenticationManager" alias="_authenticationManager"/>
 
    <bean id="passwordEncoder" class="org.springframework.security.providers.encoding.ShaPasswordEncoder"/>
 
    <!-- which service (application) am I authenticating -->
    <bean id="serviceProperties" class="org.springframework.security.ui.cas.ServiceProperties">
        <property name="service" value="https://localhost:5543/for/j_spring_cas_security_check"/>
        <property name="sendRenew" value="false"/>
    </bean>
 
    <!-- handles a logout request from the CAS server -->
    <bean id="casSingleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
 
    <!-- performs CAS authentication -->
    <bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationFailureUrl" value="/403.jsp"/>
        <property name="alwaysUseDefaultTargetUrl" value="false"/>
        <property name="defaultTargetUrl" value="/"/>
    </bean>
 
    <!-- Does the CAS ticket validation and user details loading -->
    <bean id="casAuthenticationProvider" class="org.springframework.security.providers.cas.CasAuthenticationProvider">
        <property name="userDetailsService" ref="pickYourUserDetailsServiceImplementation"/>
        <property name="serviceProperties" ref="serviceProperties"/>
        <property name="ticketValidator">
            <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <constructor-arg index="0" value="https://localhost:5543/cas"/>
            </bean>
        </property>
        <property name="key" value="my_password_for_this_auth_provider_only"/>
    </bean>
 
    <!-- Log failed authentication attempts to commons-logging -->
    <bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
 
    <bean id="httpSessionContextIntegrationFilter"
          class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
 
    <bean id="securityContextHolderAwareRequestFilter"
          class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter"/>
 
    <!-- ===================== SSL SWITCHING ==================== -->
    <bean id="channelProcessingFilter" class="org.springframework.security.securechannel.ChannelProcessingFilter">
        <property name="channelDecisionManager" ref="channelDecisionManager"/>
        <property name="filterInvocationDefinitionSource">
            <value>
                PATTERN_TYPE_APACHE_ANT
                **=REQUIRES_SECURE_CHANNEL
            </value>
        </property>
    </bean>
 
    <bean id="channelDecisionManager" class="org.springframework.security.securechannel.ChannelDecisionManagerImpl">
        <property name="channelProcessors">
            <list>
                <bean class="org.springframework.security.securechannel.SecureChannelProcessor">
                    <property name="entryPoint" ref="channelEntryPoint"/>
                </bean>
                <bean class="org.springframework.security.securechannel.InsecureChannelProcessor">
                    <property name="entryPoint" ref="channelEntryPoint"/>
                </bean>
            </list>
        </property>
    </bean>
 
    <bean id="channelEntryPoint" class="org.springframework.security.securechannel.RetryWithHttpsEntryPoint">
        <property name="portMapper" ref="portMapper"/>
    </bean>
 
    <bean id="portMapper" class="org.springframework.security.util.PortMapperImpl">
        <property name="portMappings">
            <map>
                <entry key="80" value="443"/>
                <entry key="8080" value="8443"/>
                <entry key="5580" value="5543"/>
            </map>
        </property>
    </bean>
 
    <!-- Invoked when the user clicks logout -->
    <bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
        <!-- URL redirected to after logout success -->
        <constructor-arg value="https://localhost:5543/cas/logout"/>
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler">
                    <property name="invalidateHttpSession" value="false"/>
                </bean>
            </list>
        </constructor-arg>
    </bean>
 
</beans>

-Matt

Problem with security.xml

Here it is what I found in my log :

19 janv. 2010 15:20:46 org.apache.catalina.core.StandardContext listenerStart
GRAVE: Exception lors de l'envoi de l'�v�nement contexte initialis� (context initialized) � l'instance de classe d'�coute (listener) org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 10 in XML document from ServletContext resource [/WEB-INF/context/security.xml] is invalid; nested exception is org.xml.sax.SAXParseException: The prefix "sec" for element "sec:http" is not bound.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:404)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.kablink.teaming.spring.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:69)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:92)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:123)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:422)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.xml.sax.SAXParseException: The prefix "sec" for element "sec:http" is not bound.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
... 37 more
19 janv. 2010 15:20:46 org.apache.catalina.core.StandardContext listenerStart
GRAVE: Exception lors de l'envoi de l'�v�nement contexte initialis� (context initialized) � l'instance de classe d'�coute (listener) org.kablink.teaming.web.servlet.listener.ContextListener
java.lang.NullPointerException
at org.kablink.teaming.util.SpringContextUtil.getBean(SpringContextUtil.java:117)
at org.kablink.teaming.web.servlet.listener.ContextListener.contextInitialized(ContextListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

Here is my file security.xml :

Matt Fleming's picture

You need to add the namespace...

Look at the declaration in my xml file. This is where you define the xml namespaces.. in your case you're missing the sec stuff.
-Matt

Thank you Matt. You were

Thank you Matt.
You were right.

Now I have another problem :

GRAVE: Exception lors de l'envoi de l'�v�nement contexte initialis� (context initialized) � l'instance de classe d'�coute (listener) org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainProxy': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainList': Cannot resolve reference to bean '_exceptionTranslationFilter' while setting bean property 'filters' with key [2]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_exceptionTranslationFilter': Initialization of bean failed; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.security.ui.cas.CasProcessingFilterEntryPoint] for bean with name 'casProcessingFilterEntryPoint' defined in ServletContext resource [/WEB-INF/context/security.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainList': Cannot resolve reference to bean '_exceptionTranslationFilter' while setting bean property 'filters' with key [2]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_exceptionTranslationFilter': Initialization of bean failed; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.security.ui.cas.CasProcessingFilterEntryPoint] for bean with name 'casProcessingFilterEntryPoint' defined in ServletContext resource [/WEB-INF/context/security.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:287)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1245)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.security.config.FilterChainProxyPostProcessor.postProcessBeforeInitialization(FilterChainProxyPostProcessor.java:52)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1331)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
... 38 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_exceptionTranslationFilter': Initialization of bean failed; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.security.ui.cas.CasProcessingFilterEntryPoint] for bean with name 'casProcessingFilterEntryPoint' defined in ServletContext resource [/WEB-INF/context/security.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
... 56 more
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.security.ui.cas.CasProcessingFilterEntryPoint] for bean with name 'casProcessingFilterEntryPoint' defined in ServletContext resource [/WEB-INF/context/security.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1141)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1105)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:386)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.security.config.EntryPointInjectionBeanPostProcessor.postProcessBeforeInitialization(EntryPointInjectionBeanPostProcessor.java:37)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1331)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
... 65 more
Caused by: java.lang.ClassNotFoundException: org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:385)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1138)
... 78 more

Do you know how I can have the class org.springframework.security.ui.cas ?

Thanks

Matt Fleming's picture

It's found in spring-security-cas-client jar

I don't know how you do dependencies in your project, but here's how you do it in maven:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-cas-client</artifactId>
    <version>2.0.4</version>
</dependency>

-Matt

What is UserDetailsService?

What is UserDetailsService? Which value must we put in security.xml?

Matt Fleming's picture

Roll your own or pick an existing one.

The one listed in the xml file is a custom bean. There are plenty of existing implementations though. Check out the javadoc

-Matt

I have this error when I log

I have this error when I log in the website :

java.lang.ClassCastException: org.kablink.teaming.asmodule.spring.security.config.TeamingAuthenticationManager cannot be cast to org.kablink.teaming.security.authentication.AuthenticationManager

Do you know how I can fix it?

Thanks
Laura

Matt Fleming's picture

Not really

Those sound like completely custom implementations. Does TeamingAuthenticationManager extend/implement AuthenticationManager?

-Matt

Matt Fleming's picture

Here's the concise security.xml configuration

Here's the concise version of the security configuration. This isn't something that you would be able to totally copy and paste of course. At a minimum the ROLEs are going to be different, as well as the service and userDetailsService definition.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                                                http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
 
    <sec:http lowercase-comparisons="false" entry-point-ref="casProcessingFilterEntryPoint">
        <sec:intercept-url pattern="/images/*" filters="none"/>
        <sec:intercept-url pattern="/styles/*" filters="none"/>
        <sec:intercept-url pattern="/scripts/*" filters="none"/>
        <sec:intercept-url pattern="/403.jsp" filters="none"/>
        <sec:intercept-url pattern="/404.jsp" filters="none"/>
        <sec:intercept-url pattern="/error.jsp" filters="none"/>
        <sec:intercept-url pattern="/**/*.html*"
                           access="ROLE_ALLOWED_ROLES_GO_HERE"
                           requires-channel="https"/>
        <sec:logout logout-success-url="https://localhost:5543/cas/logout" invalidate-session="false"/>
        <sec:port-mappings>
            <sec:port-mapping http="5580" https="5543"/>
            <sec:port-mapping http="80" https="443"/>
        </sec:port-mappings>
    </sec:http>
 
    <bean id="passwordEncoder" class="org.springframework.security.providers.encoding.ShaPasswordEncoder"/>
 
    <!-- where do I go when I need authentication -->
    <bean id="casProcessingFilterEntryPoint" class="org.springframework.security.ui.cas.CasProcessingFilterEntryPoint">
        <property name="loginUrl" value="https://localhost:5543/cas/login"/>
        <property name="serviceProperties" ref="serviceProperties"/>
    </bean>
 
    <!-- which service (application) am I authenticating -->
    <bean id="serviceProperties" class="org.springframework.security.ui.cas.ServiceProperties">
        <property name="service" value="https://localhost:5543/rtos/j_spring_cas_security_check"/>
        <property name="sendRenew" value="false"/>
    </bean>
 
    <sec:authentication-manager alias="authenticationManager"/>
 
    <bean id="casSingleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
        <sec:custom-filter before="CAS_PROCESSING_FILTER"/>
    </bean>
 
    <bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
        <sec:custom-filter after="CAS_PROCESSING_FILTER"/>
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationFailureUrl" value="/403.jsp"/>
        <property name="defaultTargetUrl" value="/"/>       
    </bean>
 
    <bean id="casAuthenticationProvider" class="org.springframework.security.providers.cas.CasAuthenticationProvider">
        <sec:custom-authentication-provider/>
        <property name="userDetailsService" ref="pickAnImplementationOfUserDetailsServiceOrRollYourOwn"/>
        <property name="serviceProperties" ref="serviceProperties"/>
        <property name="ticketValidator">
            <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <constructor-arg index="0" value="https://localhost:5543/cas"/>
            </bean>
        </property>
        <property name="key" value="my_password_for_this_auth_provider_only"/>
    </bean>
 
    <!-- Log failed authentication attempts to commons-logging -->
    <bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
 
</beans>

-Matt

Why this (security.xml) is different from securityContext.xml?

I download CAS 3.3.5 and they have applicationcontext.xml and securityContext.xml. The securityContext.xml has different name and format
from your security.xml. Why? and how Spring Security knows named "security.xml" or "securityContext.xml"? where is defined?

Thank you

Matt Fleming's picture

In the actual CAS application?

In the actual CAS application, they have some kind of manager application. As far as I can tell, it really isn't necessary at all to enable. In general, "how spring knows which xml files to load" is based upon how the spring container is instantiated. In most web apps, people use a servlet filter to instantiate the container on each request.. so you would see configuration in the web.xml. The question isn't specific to spring security though.. it's really a spring in general question. You should really read the documentation on how to instantiate a spring container; it is well written and explains everything.

-Matt