春季安全使用多个身份验证提供 - UsernameNotFoundException(Spring

2019-10-20 08:27发布

我们有2所身份验证提供弹簧安全配置:一为人类用户,第二个用于其他的web应用(通过REST)。 见我刚才的问题: 春季安全Web服务和用户

现在,问题是,当web应用程序发送的用户名+通,弹簧安全首先尝试用户认证提供者,失败,并且然后尝试其余验证提供。

这导致org.springframework.security.core.userdetails.UsernameNotFoundException在日志中,即使剩下的认证是最终成功。 有没有一种方法,以防止这种情况发生?

配置是:

security.xml文件:

<security:http use-expressions="true">
    <security:intercept-url pattern="/user/login"
        access="permitAll" />
             ...
    <security:intercept-url pattern="/**"
        access="isAuthenticated()" />

    <security:form-login
        authentication-success-handler-ref="userAuthenticationSuccessHandler" />

    <security:logout logout-url="/user/logout"
        logout-success-url="/demo/user/logoutSuccess" />
</security:http>

<bean id="bCryptPasswordEncoder"
    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider
        ref="authenticationProvider">
    </security:authentication-provider>
    <security:authentication-provider
        ref="restAuthenticationProvider">
    </security:authentication-provider>
</security:authentication-manager>

休息-security.xml文件:

<security:http create-session="stateless"
    entry-point-ref="digestEntryPoint" pattern="/provider/**"
    use-expressions="true">
    <security:intercept-url pattern="/provider/**"
        access="isAuthenticated()" />

    <security:http-basic />
    <security:custom-filter ref="digestFilter"
        after="BASIC_AUTH_FILTER" />
</security:http>

<bean id="digestFilter"
    class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
    <property name="userDetailsService" ref="webappDetailsServiceImpl" />
    <property name="authenticationEntryPoint" ref="digestEntryPoint" />
</bean>

<bean id="digestEntryPoint"
    class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
    <property name="realmName" value="Contacts Realm via Digest Authentication" />
    <property name="key" value="acegi" />
</bean>

日志:

22 Jun 2014 10:43:46 ERROR LoggingAspect - Unhandled exception caught: ...UserDetailsServiceImpl    loadUserByUsername
org.springframework.security.core.userdetails.UsernameNotFoundException: User with loginName: *** doesnt exist
at ...UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:30)
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:102)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:168)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
22 Jun 2014 10:43:47  INFO LoggingAspect - Entering: ...WebappDetailsServiceImpl    Method name: loadUserByUsername Method arguments : [1]

Answer 1:

这堆栈跟踪来自你自己的代码:UserDetailsS​​erviceImpl行30

根据Spring文档:

AuthenticationProviders通常按顺序尝试直到一个提供了一个非空响应。 非空的响应指示提供有权力决定的认证请求并没有进一步提供商都试过了。

发生什么了 ?

第一个AuthenticationManager会(豆:AuthenticationProvider的)被调用,并抛出一个UserNameNotFoundException。 这是确定的和预期的,因为必须验证失败,这一个,必须成功与restAnthenticationProvider

堆栈跟踪由您LoggingAspect打印,问题是存在的 。 LoggingAspect抱怨“意外的异常”,但是这一个并不意外。 这个bean的AuthenticationProvider是完全尊重合同,并抛出预期的异常。 所以修复LoggingAspect,使其不要抱怨这个例外。

需要注意的是:简单的颠倒身份验证提供者的声明顺序将解决该问题(至少对于所有其他要求)。 这种快速解决方法的缺点是,有很好的机会,你会得到一个相当于例外所有人类认证请求,因为所有的人都会第一失效对restAuthenticationProvider。



文章来源: Spring security with multiple authentication providers - UsernameNotFoundException