Spring Security and CAS Integration

Rajesh picture Rajesh · Mar 23, 2012 · Viewed 24.2k times · Source

Can anyone paste simple steps to integrate Spring security and CAS over here for single sign on and single sign out. Note I dont want any role based access.I have a web application which is already integrated with spring security. Now I was trying to perform SSO with CAS,but I am getting this error sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

This is my current spring security.xml

       <?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        ">

<sec:http entry-point-ref="casProcessingFilterEntryPoint" >
        <sec:intercept-url pattern="/**" access="ROLE_USER" />
        <sec:logout logout-success-url="/loggedout.jsp" invalidate-session="true"/>
        <sec:custom-filter ref="casAuthenticationFilter" after="CAS_FILTER"/>
    </sec:http>

    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider ref="casAuthenticationProvider"/>
    </sec:authentication-manager>

<bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationFailureHandler">
            <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <property name="defaultFailureUrl" value="/casfailed.jsp"/>
            </bean>
        </property>
        <property name="authenticationSuccessHandler">
            <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
                <property name="defaultTargetUrl" value="/"/>
            </bean>
        </property>
    </bean>

    <bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
        <property name="loginUrl" value="https://cegicollabdev.india.xxx.com:8443/cas/login"/>
        <property name="serviceProperties" ref="serviceProperties"/>
    </bean>

    <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
        <property name="userDetailsService" ref="userService"/>
        <property name="serviceProperties" ref="serviceProperties" />
        <property name="ticketValidator">
            <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
                <constructor-arg index="0" value="https://cegicollabdev.india.tcs.com:8443/cas" />
                </bean>
        </property>
        <property name="key" value="an_id_for_this_auth_provider_only"/>
    </bean>


    <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
        <property name="service" value="http://localhost:8080/dbcomparision/j_spring_cas_security_check"/>
        <property name="sendRenew" value="false"/>
    </bean>

    <bean id="userService" class="com.tcs.ceg.services.impl.UserServiceImpl" />

 <!--     <sec:global-method-security pre-post-annotations="enabled" />

    <sec:http pattern="/css/**" security="none"/>
    <sec:http pattern="/images/**" security="none"/>
    <sec:http pattern="/js/**" security="none"/>
    <sec:http pattern="/index.jsp" security="none"/>
    <sec:http pattern="/app/addNewUser.json" security="none"/>
    <sec:http pattern="/dbcomplogin.jsp" security="none"/>
    <sec:http pattern="/loggedout.jsp" security="none"/>

    <sec:http use-expressions="true">-->
        <!--
             Allow all other requests. In a real application you should
             adopt a whitelisting approach where access is not allowed by default
          -->
      <!--    <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login login-page='/dbcomplogin.jsp'
          authentication-failure-url="/dbcomplogin.jsp?login_error=1"
          default-target-url="/index.jsp" />
        <sec:logout logout-success-url="/loggedout.jsp" delete-cookies="JSESSIONID"/>
        <sec:remember-me />

    </sec:http>

    <bean id="myUserService" class="com.tcs.ceg.services.impl.UserServiceImpl" />
    <sec:authentication-manager>
    <sec:authentication-provider user-service-ref="myUserService" />
    </sec:authentication-manager> -->

</beans>

This is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Spring3MVC</display-name>
  <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-rootcontext.xml
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>
      <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--
      - Loads the root application context of this web app at startup.
    -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
 <filter>
       <filter-name>CAS Single Sign Out Filter</filter-name>
       <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
    </filter>
 <filter-mapping>
       <filter-name>CAS Single Sign Out Filter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>

</web-app>

This is my Spring-rootcontext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" >
  <context:annotation-config />
 <mvc:annotation-driven />
    <context:component-scan
        base-package="com.tcs.ceg" />

 <jee:jndi-lookup id="dataSource1" jndi-name="jdbc/PmdDS"/>


    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource1" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="current_session_context_class">thread</prop>
                <prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
            </props>
        </property>
    </bean>



    <tx:annotation-driven />
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    </beans>

This is my spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" >



    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
        <value>
            org.springframework.web.servlet.view.tiles2.TilesView
        </value>
    </property>
    </bean>
    <bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/tiles.xml</value>
        </list>
    </property>
</bean>
<bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

<bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lang" />
</bean>

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="en"/>
</bean>

<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <ref bean="localeChangeInterceptor" />
    </property>
</bean>



    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- one of the properties available; the maximum file size in bytes -->
        <property name="maxUploadSize" value="1000000000000"/>
    </bean>
</beans>

Problem : 1 sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Problem 2: Custom UserServiceimpl is not getting called

Problem 3: Is this correct ? <property name="service" value="http://localhost:8080/dbcomparision/j_spring_cas_security_check"/> ,Note In my program no Request Mapping is there for j_spring_cas_security_check

Answer

Shaun the Sheep picture Shaun the Sheep · Mar 23, 2012

The simplest steps to getting CAS authentication working is to build and run the CAS sample from the Spring Security source tree.

You really need to understand how CAS works before you try to use it, or integrate it with your application. I would start on the CAS documentation and the Spring Security reference manual which describes the interactions between CAS and Spring Security.

j_spring_cas_security_check is the URL which the CAS redirects to in your application after it has authenticated the user (see the above link).

Even if your application isn't authenticating users, it still typically has a concept of users it knows about. It also has to load the roles for these users, which CAS doesn't handle, hence the user-service declaration. The password won't be used.

How your application validates that a login is successful is explained in documentation above. It basically calls the CAS server, passing in the service ticket and gets back a response with the username.