Announcement Announcement Module
Collapse
No announcement yet.
Custom X509AuthenticationFilter Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Custom X509AuthenticationFilter

    Hi,

    I have extended the X509AuthenticationFilter and I try to use it in my application but it doesn't work. I am not sure if what I am doing is right and I try to follow Peter'book instructions.

    I really need your help.
    Thank you.

    Here is my code

    Code:
    <?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:jdbc="http://www.springframework.org/schema/jdbc"
            xmlns:security="http://www.springframework.org/schema/security"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schem...-beans-3.0.xsd
                    http://www.springframework.org/schema/aop
    http://www.springframework.org/schem...ng-aop-3.0.xsd
                    http://www.springframework.org/schema/jdbc 
    http://www.springframework.org/schem...g-jdbc-3.0.xsd
                    http://www.springframework.org/schema/context
    http://www.springframework.org/schem...ontext-3.0.xsd
                    http://www.springframework.org/schema/security        http://www.springframework.org/schem...curity-3.0.xsd
            ">
            
            <bean id="x509Filter" class="CustomX509Filter">
                    <property name="authenticationManager" ref="authenticationManager"/>
            </bean>
            
            <bean id="preauthAuthenticationProvider"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
                    <property name="preAuthenticatedUserDetailsService" ref="jdbcUserServiceCustom"/>
            </bean>        
            
            <bean id="springSecurityFilterChain"
    class="org.springframework.security.web.FilterChainProxy">
              <security:filter-chain-map path-type="ant">
                 <security:filter-chain pattern="/**" filters="
                       securityContextPersistenceFilter,
                       x509Filter,
                       anonymousProcessingFilter,
                       exceptionTranslationFilter,
                       filterSecurityInterceptor" />
              </security:filter-chain-map>
            </bean>
            
            <bean id="customAuthenticationManager"
    class="org.springframework.security.authentication.ProviderManager">
                    <property name="authenticationEventPublisher" ref="defaultAuthEventPublisher"/>
                    <property name="providers">
                            <list>
                                    <ref local="preauthAuthenticationProvider"/>
                            </list>
                    </property>
            </bean>
            <bean id="jdbcUserServiceCustom"
    class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
                    <property name="dataSource" ref="dataSource"/>
            </bean>                
    </beans>
    Code:
    and that's the error I have 
    org.springframework.beans.factory.BeanCreationException: Error creating bean with
    name
    'org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices#0':
    Initialization of bean failed; nested exception is
    org.springframework.context.ApplicationContextException: More than one
    UserDetailsService registered. Please use a specific Id reference in <remember-me/>
    <openid-login/> or <x509 /> elements.

  • #2
    There error looks like it is coming from a different configuration than the one you've posted.

    Comment


    • #3
      Maybe should I join my web.xml file and applicationContext-security.xml. Here They are.

      In my applicationContext-security.xml, I'm not sure whether I sould have the <x509/> tag or not.

      Code:
      <?xml version="1.0" encoding="UTF-8"?>
      <beans:beans xmlns="http://www.springframework.org/schema/security"
          xmlns:beans="http://www.springframework.org/schema/beans"
          xmlns:jdbc="http://www.springframework.org/schema/jdbc"
          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-3.0.xsd
                              http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
                              http://www.springframework.org/schema/security
      http://www.springframework.org/schema/security/spring-security-3.0.xsd">
      
          <global-method-security pre-post-annotations="enabled">
              <!-- AspectJ pointcut expression that locates our "post" method and applies
      security that way
              <protect-pointcut expression="execution(* bigbank.*Service.post*(..))"
      access="ROLE_TELLER"/>
              -->
          </global-method-security>
          
      
      
          <http use-expressions="true">
              <intercept-url pattern="/secure/extreme/**"
      access="hasRole('ROLE_SUPERVISOR')"/>
              <intercept-url pattern="/secure/**" access="isAuthenticated()" />
              <!-- Disable web URI authorization, as we're using <global-method-security>
      and have @Secured the services layer instead
              <intercept-url pattern="/listAccounts.html" access="isRememberMe()" />
              <intercept-url pattern="/post.html" access="hasRole('ROLE_TELLER')" />
              -->
              <intercept-url pattern="/**" access="permitAll" requires-channel="https" />
              <form-login />
              <logout />
              <remember-me />
      <!--
          Uncomment to enable X509 client authentication support -->
      <!--        <x509 subject-principal-regex="CN=(.*?)," />-->
      
              <!-- Uncomment to limit the number of sessions a user can have -->
              <session-management invalid-session-url="/timeout.jsp">
                  <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
              </session-management>
      
          </http>
      
          <!--
          Usernames/Passwords are
              rod/koala
              dianne/emu
              scott/wombat
              peter/opal
          -->
          
      <!--    <authentication-manager>-->
      <!--        <authentication-provider>-->
      <!--         -->
      <!--            <password-encoder hash="md5"/>-->
      <!--            <user-service>-->
      <!--                <user name="rod" password="a564de63c2d0da68cf47586ee05984d7"
      authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />-->
      <!--                <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e"
      authorities="ROLE_USER,ROLE_TELLER" />-->
      <!--                <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a"
      authorities="ROLE_USER" />-->
      <!--                <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8"
      authorities="ROLE_USER" />-->
      <!--            </user-service>-->
      <!--            -->
      <!--        </authentication-provider>-->
      <!--         -->
      <!--    </authentication-manager>-->
               
          <authentication-manager alias="authenticationManager">
                      <authentication-provider>
                              <jdbc-user-service data-source-ref="dataSource"/>
                              <password-encoder hash="md5"/>
                      </authentication-provider>
              </authentication-manager>
              
                
              <jdbc:embedded-database id="dataSource" type="HSQL">
                      <jdbc:script location="/WEB-INF/security-schema.sql"/>
                      <jdbc:script location="/WEB-INF/test-data.sql"/>
              </jdbc:embedded-database>
      
      
      </beans:beans>
      Code:
      <?xml version="1.0" encoding="UTF-8"?>
      <!--
        - Tutorial web application
        -
        -->
      
      <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
      
          <display-name>Spring Security Tutorial Application</display-name>
      
          <!--
            - Location of the XML file that defines the root application context
            - Applied by ContextLoaderListener.
            -->
          <context-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>
      <!--            classpath:applicationContext-business.xml-->
                  /WEB-INF/applicationContext-security.xml
                  /WEB-INF/base-security.xml
              </param-value>
          </context-param>
      
          <context-param>
              <param-name>log4jConfigLocation</param-name>
              <param-value>/WEB-INF/classes/log4j.properties</param-value>
          </context-param>
      
          <context-param>
              <param-name>webAppRootKey</param-name>
              <param-value>tutorial.root</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.
            - The application context is then available via
            - WebApplicationContextUtils.getWebApplicationContext(servletContext).
          -->
          <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>
      
          <!--
            - Publishes events for session creation and destruction through the application
            - context. Optional unless concurrent session control is being used.
            -->
          <listener>
            <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
          </listener>
      
          <listener>
              <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
          </listener>
      
        <!--
          - Provides core MVC application controller. See contacts-servlet.xml.
          -->
          <servlet>
              <servlet-name>bank</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
          </servlet>
      
          <servlet-mapping>
              <servlet-name>bank</servlet-name>
              <url-pattern>*.html</url-pattern>
           </servlet-mapping>
      
           <welcome-file-list>
              <welcome-file>index.jsp</welcome-file>
          </welcome-file-list>
      
      </web-app>

      Comment


      • #4
        So you have two security configuration files, one using the namespace and one configuring its own FilterChainProxy. Use one approach or the other, but not both in combination.

        I would make sure you can get a standard setup running before you try adding custom filters. If you want to use a custom X509 filter then you would not add the x509 element as this will add the standard filter.

        Comment


        • #5
          Hi i am trying to write a file with only spring beans configuration but i am having some problems.I know that I have to replicate the funtionality of <global-method-security> but i don't know how. I have an error saying that No visible WebInvocationPrivilegeEvaluator instance could be found in the application context.

          Here is my new security.xml file.

          Code:
          ...
                  <bean id="springSecurityFilterChain"
          class="org.springframework.security.web.FilterChainProxy">
                    <security:filter-chain-map path-type="ant">
                       <security:filter-chain pattern="/**" filters="
                             securityContextPersistenceFilter,
                             logoutFilter,
                             usernamePasswordProcessingFilter,
                             rememberMeProcessingFilter,
                             anonymousProcessingFilter,
                             exceptionTranslationFilter,
                             filterSecurityInterceptor" />
                    </security:filter-chain-map>
                  </bean>
                  
                  <bean id="securityContextPersistenceFilter"
          class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
                  <bean id="usernamePasswordProcessingFilter"
          class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
          <!--          <property name="filterProcessesUrl" value="/j_spring_security_check"/>
                     <property name="usernameParameter" value="login_username"/>
                    <property name="passwordParameter" value="login_password"/> -->
                    <property name="authenticationManager" ref="customAuthenticationManager"/>
                    <property name="rememberMeServices" ref="rememberMeServices"/>
          <!--          <property name="rememberMeServices" ref="rememberMeServices"/>-->
          <!--          <property name="authenticationFailureHandler"
          ref="authenticationFailureHandler"/>-->
                  </bean>        
                  
          <!--        It's used to allow access to anonymous and define their username and granted
          authority-->
          
                  <bean id="anonymousProcessingFilter"
          class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
                  <!-- Both of these are required -->
                          <!-- username, default role -->
                          <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
                          <!-- randomly generated key -->
                          <property name="key" value="BF93JFJ091N00Q7HF"/>
                  </bean>
                  
          <!--        It's the final filter wich determines wether or not a request is rejected or
          accepted-->
                  <bean id="filterSecurityInterceptor"
          class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
                    <property name="authenticationManager" ref="customAuthenticationManager"/>
                    <property name="accessDecisionManager" ref="affirmativeBased"/>
                    <property name="securityMetadataSource">
                    <!-- SEC-1256 -->
                      <security:filter-security-metadata-source >
                                  <security:intercept-url pattern="/secure/extreme/*"
          access="IS_AUTHENTICATED_ANONYMOUSLY"/>
                                  <security:intercept-url pattern="/secure/*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
                                  <security:intercept-url pattern="/*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
          <!--                        <security:intercept-url pattern="/**" access="permitAll"
          requires-channel="https"/>-->
                      </security:filter-security-metadata-source>
                    <!-- 
                      <security:filter-security-metadata-source>
                                  <security:intercept-url pattern="/login.do" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
                                  <security:intercept-url pattern="/home.do" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
                                  <security:intercept-url pattern="/account/*.do" access="ROLE_USER"/>
                                  <security:intercept-url pattern="/*" access="ROLE_USER"/>
                      </security:filter-security-metadata-source>
                      -->
                    </property>
                  </bean>
                  
          <!--        The following is a set of bean needed to complete the minimal supporting object
          set. It provides us -->
          <!--        with a minimal configuration that supports anonymous browsing, login, and
          database-backed authentication-->
                  <bean class="org.springframework.security.access.vote.AffirmativeBased"
          id="affirmativeBased">
                          <property name="decisionVoters">
                                  <list>
                                          <ref bean="roleVoter"/>
                                          <ref bean="expressionVoter"/>
                                          <ref bean="authenticatedVoter"/>
                                  </list>
                          </property>
                  </bean>
                  
                  <bean class="org.springframework.security.access.vote.RoleVoter" id="roleVoter"/>
                  
                  <bean class="org.springframework.security.access.vote.AuthenticatedVoter"
          id="authenticatedVoter"/>
                  
                  <bean id="daoAuthenticationProvider"
          class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                  <!-- 
                          <property name="passwordEncoder" ref="passwordEncoder"/>
                          <property name="saltSource" ref="saltSource"/>
                           -->
                          <property name="userDetailsService" ref="jdbcUserServiceCustom"/>
                  </bean>
          <!--        Apparently this bean isn't needed-->
          <!--        <bean id="anonymousAuthenticationProvider"
          class="org.springframework.security.web.authentication.AnonymousAuthenticationProvider">-->
          <!--                <property name="key" value="BF93JFJ091N00Q7HF"/>-->
          <!--        </bean>-->
                  
                  <bean id="customAuthenticationManager"
          class="org.springframework.security.authentication.ProviderManager">
          <!--                <property name="authenticationEventPublisher"
          ref="defaultAuthEventPublisher"/>-->
                          <property name="providers">
                                  <list>
                                          <ref local="daoAuthenticationProvider"/>
                                          <ref local="rememberMeAuthenticationProvider"/>
                                  </list>
                          </property>
                  </bean>
                  
          <!--        Filter for loging out-->
                  <bean id="logoutFilter"
          class="org.springframework.security.web.authentication.logout.LogoutFilter">
                          <!-- the post-logout destination -->
                          <constructor-arg value="/"/>
                           <constructor-arg>
                                  <array>
                                          <ref local="logoutHandler"/>
                                          <ref local="rememberMeServices"/>
                                  </array>
                          </constructor-arg>
                          <property name="filterProcessesUrl" value="/logout"/>
                  </bean>
                  
                  <bean id="logoutHandler"
          class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
                  
                  <bean id="rememberMeProcessingFilter"
          class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
                    <property name="rememberMeServices" ref="rememberMeServices"/>
                    <property name="authenticationManager" ref="customAuthenticationManager" />
                  </bean>
                  
                  <bean id="rememberMeServices"
          class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
                          <property name="key" value="jbcpPetStore"/>
                          <property name="tokenValiditySeconds" value="3600"/>
                          <property name="tokenRepository" ref="jdbcRememberMeTokenRepository"/>
                          <property name="userDetailsService" ref="jdbcUserServiceCustom"/>
                  </bean>
                  
                  <bean id="jdbcRememberMeTokenRepository"
          class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
                          <property name="dataSource" ref="dataSource"/>
                  </bean>
                  
                  <bean id="rememberMeAuthenticationProvider"
          class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
                    <property name="key" value="jbcpPetStore"/>
                  </bean>
                  
                  <bean id="exceptionTranslationFilter"
          class="org.springframework.security.web.access.ExceptionTranslationFilter">
                    <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
                    <property name="accessDeniedHandler" ref="accessDeniedHandler"/>
                  </bean>
                  
                  <bean id="authenticationEntryPoint"
          class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                    <property name="loginFormUrl" value="/j_spring_security_check"/>
                  </bean>
                  
                  <bean id="accessDeniedHandler"
          class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                    <property name="errorPage" value="/accessDenied.do"/>
                  </bean>
                  
                  <bean
          class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"
          id="expressionHandler"/>
                  <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"
          id="expressionVoter">
                          <property name="expressionHandler" ref="expressionHandler"/>                
                  </bean>
           
                  <!-- Ch 4 In-memory HSQLDB -->        
                  <jdbc:embedded-database id="dataSource" type="HSQL">
                          <jdbc:script location="/WEB-INF/security-schema.sql"/>
                          <jdbc:script location="/WEB-INF/test-data.sql"/>
                  </jdbc:embedded-database>
                  
                  <bean id="jdbcUserServiceCustom"
          class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
                          <property name="dataSource" ref="dataSource"/>
                  </bean>        
                  </beans>

          Comment


          • #6
            If you have an error message, then do a forum/google search for the error message.

            Comment


            • #7
              Ok thank you so now I can authenticate a user with a certificate using the CN, but I would like to authenticate someone using the serial number of the certificate.
              Do you know how can i do this ?

              Comment


              • #8
                Problem solved i have implemented a custom X509PrincipalExtractor.

                Comment


                • #9
                  Originally posted by wasalto View Post
                  Problem solved i have implemented a custom X509PrincipalExtractor.
                  I am trying to do this exact same thing and somehow I have lost my authentication providers. Would it be possible for you to post your application security context file so I can see how you wired in the providers.

                  Thanks,

                  Chris

                  Comment

                  Working...
                  X