Spring security DaoAuthenticationProvider不允许使用相同的凭据重新登录

Spring security DaoAuthenticationProvider不允许使用相同的凭据重新登录,spring-security,Spring Security,我们的应用程序在Spring2.5中使用了JSP和acegisecurity。我们正在尝试将其移植到Spring3中使用SpringSecurity3.2.4 最初的应用程序使用基于XML的配置,所以我选择继续使用它。应用程序被设置为使用DAOAuthProvider,如果登录失败,则使用LDAP身份验证Provider 我移植了应用程序,现在它启动了。我可以使用DaoAuthenticationProvider和一个InMemoryDaoImpl bean登录到应用程序,该bean保存凭据和角

我们的应用程序在Spring2.5中使用了JSP和acegisecurity。我们正在尝试将其移植到Spring3中使用SpringSecurity3.2.4

最初的应用程序使用基于XML的配置,所以我选择继续使用它。应用程序被设置为使用DAOAuthProvider,如果登录失败,则使用LDAP身份验证Provider

我移植了应用程序,现在它启动了。我可以使用DaoAuthenticationProvider和一个InMemoryDaoImpl bean登录到应用程序,该bean保存凭据和角色

然而,我面临以下问题:

1我启动网络应用程序。 2启动后,我使用凭据登录。这很有效。 3单击注销 4输入与1相同的凭据,但在DAO提供程序中登录失败。然后它尝试使用LDAP提供程序,但显然也失败了,因为LDAP服务器中不存在用户

日志片段:

2014-07-11 11:50:28089调试[:] [org.springframework.security.web.context.SecurityContextPersistenceFilter] 请求处理完成后,SecurityContextHolder现在已清除 2014-07-11 11:50:42744调试[:] [org.springframework.security.web.util.AntPathRequestMatcher]请求 “/j_spring_security_check”与通用模式匹配“/**” 2014-07-11 11:50:42744调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置1/8处 链条触发过滤器:“SecurityCo ntextPersistenceFilter”2014-07-11 11:50:42744调试[:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession为SPRING\u SECURITY\u上下文返回空对象 2014-07-11 11:50:42744调试[:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession:org.apache.cata中没有可用的SecurityContext 丽娜,会话。StandardSessionFacade@4bbaa9f0. 一个新的 创建。2014-07-11 11:50:42744调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置2/8处 链条触发过滤器:“注销过滤器”2014-07-11 11:50:42744调试 [:][org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置3/8处 链条正在启动筛选器:“UsernamePa sswordAuthenticationFilter” 2014-07-11 11:50:42744调试[:] [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] 请求处理身份验证2014-07-11 11:50:42748调试[:] [org.springframework.security.authentication.ProviderManager] 身份验证尝试使用 org.springframework.security.authentication.dao.DaoAuthenti 定位提供者

注销交易:

2014-07-11 11:52:31058调试[:] [org.springframework.security.web.util.AntPathRequestMatcher]请求 “/j_spring_security_logout”与通用模式“/**”匹配 2014-07-11 11:52:31058调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_在附加过滤器中8的位置1处注销 链条触发筛选器:“SecurityContextPersistenceFilter”2014-07-11 11:52:31058调试[:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] 从SPRING\u SECURITY\u上下文中获取了有效的SecurityContext: 'org.springframework.security.core.context。SecurityContextImpl@873a5ff1: 身份验证: org.springframework.security.authentication。UsernamePasswordAuthenticationToken@873a5ff1: 负责人: org.springframework.security.core.userdetails。User@e6d32b12:用户名: 进口商;密码:[受保护];启用:真;AccountNoExpired: 符合事实的无需证明的凭证:真实;AccountNonLocked:true;授予 授权机构:ROLE_进口商_集团;凭据:[受保护]; 认证:正确;细节: org.springframework.security.web.authentication。WebAuthenticationDetails@12afc: RemoteIP地址:127.0.0.1;会话ID: 1B2AA0FD58F4509952385C13D2A84D56;授予的权限: 角色组“2014-07-11 11:52:31058调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_在附加过滤器中8的位置2处注销 链条触发过滤器:“注销过滤器”2014-07-11 11:52:31059调试[:] [org.springframework.security.web.authentication.logout.LogoutFilter] 注销用户 'org.springframework.security.authentication。UsernamePasswordAuthenticationToken@873a5ff1: 负责人: org.springframework.security.core.userdetails。User@e6d32b12:用户名: 进口商;密码:[受保护];启用:真;AccountNoExpired: 符合事实的无需证明的凭证:真实;AccountNonLocked:true;授予 授权机构:ROLE_进口商_集团;凭据:[受保护]; 认证:正确;细节: org.springframework.security.web.authentication。WebAuthenticationDetails@12afc: RemoteIP地址:127.0.0.1;会话ID: 1B2AA0FD58F4509952385C13 D2A84D56;授予的权限: 角色(进口商)(集团)并转移至注销目的地2014-07-11 11:52:31059调试[:] [org.springframework.security.web.authentication.memberme.TokenBasedMemberMeservices] 用户导入程序注销2014-07-11 11:52:31059调试[:] [org.springframework.security.web.authentication.memberme.TokenBasedMemberMeservices] 取消cookie 2014-07-11 11:52:31059调试[:] [org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler] 无效会话:1B2AA0FD58F4509952385C13D2A84D56 2014-07-11 11:52:31059调试[:] [org.springframework.security.web.authentication.logout.SimpleRullogoutSuccessHandler] 使用默认Url:/login.jsp 2014-07-11 11:52:31060调试[:] [org.springframework.security.web.DefaultRedirectStrategy]重定向 到“/login.jsp”

重新登录失败的事务

2014-07-11 11:52:53679调试[:] [org.springframework.security.web.util.AntPathRequestMatcher]请求 “/j_spring_security_check”与通用模式匹配“/**” 2014-07-11 11:52:53680调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置1/8处 链条触发筛选器:“SecurityContextPersistenceFilter”2014-07-11 11:52:53680调试[:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession为SPRING\u SECURITY\u上下文返回空对象 2014-07-11 11:52:53680调试[:] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] HttpSession中没有可用的SecurityContext: org.apache.catalina.session。StandardSessionFacade@12224026. 新的 将创建。2014-07-11 11:52:53680调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置2/8处 链条触发筛选器:“LogoutFilter”2014-07-11 11:52:53680调试[:] [org.springframework.security.web.FilterChainProxy] /j_弹簧_安全_检查附加过滤器中位置3/8处 链条正在启动筛选器:“UsernamePasswordAuthenticationFilter” 2014-07-11 11:52:53680调试[:] [org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter] 请求处理身份验证2014-07-11 11:52:53680调试[:] [org.springframework.security.authentication.ProviderManager] 身份验证尝试使用 org.springframework.security.authentication.dao.DaoAuthenticationProvider 2014-07-11 11:52:53680调试[:] [org.springframework.security.authentication.dao.DaoAuthenticationProvider] 身份验证失败:密码与存储值不匹配2014-07-11 11:52:53681调试[:] [org.springframework.security.authentication.ProviderManager] 身份验证尝试使用 org.springframework.security.ldap.authentication.ldapaauthenticationprovider

这是我的spring配置

    <!-- 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>

感谢您的帮助/指点

提前谢谢

编辑1:

我通过了密码。我在DaoAuthenticationProvider::additionalAuthenticationChecks中放置了一个断点。这就是正在发生的事情

第一次登录成功,UserDetails服务拥有与用户提供的密码匹配的密码。 第二次,使用相同的凭据,似乎UserDetails服务具有正确的用户名,但密码为空。因此,传入的非空密码与UserDetailsService中的空密码不匹配。因此,身份验证失败。
我发现了问题。我使用spring InMemoryDaoImpl类来存储用户名和密码。但是,根据spring depcreated api列表,该类已被弃用,取而代之的是InMemoryUserDetailsManager。当我把我的豆子换成这个时,它就像预期的那样工作

一个吹毛求疵的问题是,spring文档似乎没有跟上这一点。关于这个问题,spring security 3.2.4.0版本的文档似乎已经过时

<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>