0
votes

Our application used JSP and acegisecurity with spring 2.5. We are trying to port it to use spring-security 3.2.4 with spring 3.

The original application used XML based configuration, so I opted to continue with that. The application was setup to use a DAOAuthProvider, and if the login failed there, to use the LDAP authentication provdider.

I ported the application over, and it now starts up. I can login to the application using the DaoAuthenticationProvider with an InMemoryDaoImpl bean that holds the credentials and roles.

However, I am facing the following problem:

1) I start the webapp. 2) After startup, I login using credentials. This works. 3) Click logout 4) Enter the same credentials as #1, but the login fails in the DAO provider. It then tries to use the LDAP provider, and fails there as well, obviously, because the user does not exist in the LDAP server.

Log Snippets:

2014-07-11 11:50:28,089 DEBUG [:] [org.springframework.security.web.context.SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.util.AntPathRequestMatcher] Request '/j_spring_security_check' matched by universal pattern '/**' 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 1 of 8 in additional filter chain; firing Filter: 'SecurityCo ntextPersistenceFilter' 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession returned null object for SPRING_SECURITY_CONTEXT 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] No SecurityContext was available from the HttpSession: org.apache.cata lina.session.StandardSessionFacade@4bbaa9f0. A new one will be created. 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 2 of 8 in additional filter chain; firing Filter: 'LogoutFilt er' 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 3 of 8 in additional filter chain; firing Filter: 'UsernamePa sswordAuthenticationFilter' 2014-07-11 11:50:42,744 DEBUG [:] [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] Request is to process authentication 2014-07-11 11:50:42,748 DEBUG [:] [org.springframework.security.authentication.ProviderManager] Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenti cationProvider

Logout Transaction:

2014-07-11 11:52:31,058 DEBUG [:] [org.springframework.security.web.util.AntPathRequestMatcher] Request '/j_spring_security_logout' matched by universal pattern '/**' 2014-07-11 11:52:31,058 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_logout at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2014-07-11 11:52:31,058 DEBUG [:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@873a5ff1: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@873a5ff1: Principal: org.springframework.security.core.userdetails.User@e6d32b12: Username: importer; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_IMPORTER_GROUP; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 1B2AA0FD58F4509952385C13D2A84D56; Granted Authorities: ROLE_IMPORTER_GROUP' 2014-07-11 11:52:31,058 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_logout at position 2 of 8 in additional filter chain; firing Filter: 'LogoutFilter' 2014-07-11 11:52:31,059 DEBUG [:] [org.springframework.security.web.authentication.logout.LogoutFilter] Logging out user 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@873a5ff1: Principal: org.springframework.security.core.userdetails.User@e6d32b12: Username: importer; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_IMPORTER_GROUP; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 1B2AA0FD58F4509952385C13D2A84D56; Granted Authorities: ROLE_IMPORTER_GROUP' and transferring to logout destination 2014-07-11 11:52:31,059 DEBUG [:] [org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices] Logout of user importer 2014-07-11 11:52:31,059 DEBUG [:] [org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices] Cancelling cookie 2014-07-11 11:52:31,059 DEBUG [:] [org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler] Invalidating session: 1B2AA0FD58F4509952385C13D2A84D56 2014-07-11 11:52:31,059 DEBUG [:] [org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler] Using default Url: /login.jsp 2014-07-11 11:52:31,060 DEBUG [:] [org.springframework.security.web.DefaultRedirectStrategy] Redirecting to '/login.jsp'

Relogin Transaction ( that fails )

2014-07-11 11:52:53,679 DEBUG [:] [org.springframework.security.web.util.AntPathRequestMatcher] Request '/j_spring_security_check' matched by universal pattern '/**' 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession returned null object for SPRING_SECURITY_CONTEXT 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@12224026. A new one will be created. 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 2 of 8 in additional filter chain; firing Filter: 'LogoutFilter' 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.FilterChainProxy] /j_spring_security_check at position 3 of 8 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] Request is to process authentication 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.authentication.ProviderManager] Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 2014-07-11 11:52:53,680 DEBUG [:] [org.springframework.security.authentication.dao.DaoAuthenticationProvider] Authentication failed: password does not match stored value 2014-07-11 11:52:53,681 DEBUG [:] [org.springframework.security.authentication.ProviderManager] Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider

And here is my spring config...

    <!-- web security -->
<bean id="filterChainProxy" name="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
    <constructor-arg>
        <bean class="org.springframework.security.web.DefaultSecurityFilterChain">
            <constructor-arg>
                <bean class="org.springframework.security.web.util.AntPathRequestMatcher">
                    <constructor-arg value="/**" />
                </bean>
            </constructor-arg>
            <constructor-arg>
                <list>
                    <ref bean="httpSessionContextIntegrationFilter"/>
                    <ref bean="logoutFilter"/>
                    <ref bean="authenticationProcessingFilter"/>
                    <ref bean="securityContextHolderAwareRequestFilter"/>
                    <ref bean="rememberMeProcessingFilter"/>
                    <ref bean="anonymousProcessingFilter"/>
                    <ref bean="exceptionTranslationFilter"/>
                    <ref bean="filterInvocationInterceptor"/>
                </list>
            </constructor-arg>
        </bean>
    </constructor-arg>
</bean>

<bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg value="/login.jsp"/> <!-- URL redirected to after logout -->
    <constructor-arg>
        <list>
            <ref bean="rememberMeServices"/>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
        </list>
    </constructor-arg>
</bean>

<bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <!-- authenticationManager is obtained from dataimport-authorization-context.xml -->
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationFailureHandler">
        <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <constructor-arg value="/login.jsp?login_error=1"/>
        </bean>
    </property>
    <property name="authenticationSuccessHandler">
        <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
            <property name="defaultTargetUrl" value="/welcome"/>
        </bean>
    </property>
    <property name="filterProcessesUrl" value="/j_spring_security_check"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>

<bean id="rememberMeProcessingFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
    <!-- authenticationManager is obtained from dataimport-authorization-context.xml -->
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
</bean>

<bean id="anonymousProcessingFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
    <property name="key" value="changeThis"/>
    <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>

<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
        <bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <property name="loginFormUrl" value="/login.jsp"/>
            <property name="forceHttps" value="false"/>
        </bean>
    </property>
    <property name="accessDeniedHandler">
        <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
            <property name="errorPage" value="/accessdenied.jsp"/>
        </bean>
    </property>
</bean>

<bean id="filterInvocationInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <!-- authenticationManager is obtained from dataimport-authorization-context.xml -->
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager">
        <bean class="org.springframework.security.access.vote.AffirmativeBased">
            <property name="allowIfAllAbstainDecisions" value="false"/>
            <property name="decisionVoters">
                <list>
                    <bean class="org.springframework.security.access.vote.RoleVoter"/>
                    <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
                </list>
            </property>
        </bean>
    </property>
    <!-- property name="objectDefinitionSource">
        <value><![CDATA[
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /hello=ROLE_IMPORTER_GROUP
            /tasks=ROLE_IMPORTER_GROUP
            /import=ROLE_IMPORTER_GROUP
            /bvt=ROLE_IMPORTER_GROUP
            /process=ROLE_IMPORTER_GROUP
            /workflow=ROLE_IMPORTER_GROUP
            /listauditlog=ROLE_EDITOR_GROUP
            /editpropertytransaction=ROLE_EDITOR_GROUP
            /deleteproperty=ROLE_EDITOR_GROUP
            /deletepropertysearchresult=ROLE_EDITOR_GROUP
            /deletepropertyenqueueresult=ROLE_EDITOR_GROUP
        ]]></value>
    </property -->
    <property name="securityMetadataSource">
      <security:filter-security-metadata-source>
        <security:intercept-url pattern="/login.jsp**" access="ROLE_ANONYMOUS"/>
        <security:intercept-url pattern="/favicon.ico" access="ROLE_ANONYMOUS"/>
        <security:intercept-url pattern="/listauditlog" access="ROLE_IMPORTER_GROUP"/>
      </security:filter-security-metadata-source>
    </property>

</bean>

<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
    <property name="userDetailsService" ref="userDetailsService"/>
    <property name="key" value="changeThis"/>
</bean>

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="userDetailsService"/>
</bean>

<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
<bean id="authLoggerListener" class="org.springframework.security.authentication.event.LoggerListener">
    <property name="logInteractiveAuthenticationSuccessEvents" value="true"/>
</bean>

<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
<bean id="authzLoggerListener" class="org.springframework.security.access.event.LoggerListener">
</bean>

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
<!-- bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager" -->
    <property name="providers">
        <list>
            <!-- uncomment the following for specifying user/password/roles from an XML file.
            The usernames/password/role XML file will be dataimport-security-context.xml
            -->

            <ref bean="daoAuthenticationProvider"/>

            <!-- uncomment the following for enabling authorization using LDAP.
                LDAP settings are read from dataimport-ldap.properties 
            -->
            <ref bean="ldapAuthProvider"/>
            <bean class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
                <property name="key" value="changeThis"/>
            </bean>
            <bean class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
                <property name="key" value="changeThis"/>
            </bean>
        </list>
    </property>
</bean>

Any help/pointers appreciated.

Thanks in advance.

EDIT 1:

I stepped through the code. I put a breakpoint in DaoAuthenticationProvider::additionalAuthenticationChecks. This is what is happening.

  1. The first time, login succeeds, and a UserDetails service has the password, that matches the one supplied by the user.
  2. The second time, with the same credentials, it seems as if the UserDetails service has the correct username, but password is null. So, the incoming non-null password does not match the "null" password in the UserDetailsService. Due to this, authentication fails.
1

1 Answers

0
votes

I found the problem. I was using the spring InMemoryDaoImpl class to store the usernames and passwords. However, as per the spring depcreated api list, this class has been deprecated in favor of the InMemoryUserDetailsManager. When I switched my beans to this, it worked as expected.

One nitpick, it seems that the spring documentation has not kept up to date with this. The documentation for spring-security 3.2.4.RELEASE seems to be out of date on this issue.

http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle