如何处理Spring Security AuthenticationProviders抛出的运行时异常?

时间:2017-01-13 08:28:06

标签: java spring spring-boot spring-security exception-handling

如何处理Spring Security身份验证提供程序抛出的运行时异常?我使用的是Spring Boot 1.4.2,但我觉得这也适用于经典的Spring应用程序。

我们说我已经配置了<system.serviceModel> <services> <service behaviorConfiguration="Default" name="BlogService.Service1"> <endpoint address="" behaviorConfiguration="webBehavior" binding="webHttpBinding" contract="BlogService.IService1" bindingConfiguration="WHB" /> <host> <baseAddresses> <add baseAddress="http://localhost:60500/Service1.svc" /> </baseAddresses> </host> </service> </services> <behaviors> <endpointBehaviors> <behavior name="webBehavior"> <webHttp defaultOutgoingResponseFormat="Json" /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior> <!-- To avoid disclosing metadata information, set the values below to false before deployment --> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> <behavior name="Default"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="WHB" crossDomainScriptAccessEnabled="true"> <security mode="None" /> </binding> </webHttpBinding> </bindings> <protocolMapping> <add binding="basicHttpsBinding" scheme="https"/> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/> </system.serviceModel>来根据我的公司AD对用户进行身份验证。当身份验证因验证失败而导致身份验证失败时,这一切都适用于Spring Security(抛出ActiveDirectoryLdapAuthenticationProvider,由Spring Security机制正确处理=应用程序返回登录屏幕并显示身份验证错误)

然而有时,AD会暂时停止并且会引发AuthenticationException。此异常是运行时异常,因此不受Spring安全机制的限制,因为它不会扩展org.springframework.ldap.CommunicationException

在这种情况下会发生的是,应用程序被重定向到默认错误页面(这是/错误)。我想要做的是仍然显示带有自定义消息的登录屏幕。

如果我创建类似

的内容,我发现我可以这样做
AuthenticationException

这有效,但我觉得必须有更好的方法。

我已尝试创建一个public class ActiveDirectoryLdapExtendedAuthenticationProvider implements AuthenticationProvider { private final ActiveDirectoryLdapAuthenticationProvider adAuthenticationProvider; public ActiveDirectoryLdapExtendedAuthenticationProvider(ActiveDirectoryLdapAuthenticationProvider adAuthenticationProvider) { this.adAuthenticationProvider = adAuthenticationProvider; } @Override public Authentication authenticate(Authentication a) throws AuthenticationException { Authentication auth = null; try { auth = adAuthenticationProvider.authenticate(a); } catch(CommunicationException communicationException) { throw new AuthenticationServiceException("Could not reach User Directory. Please try again in a few minutes"); } return auth; } 带注释的类,但它不会被POST调用以由Spring Security登录。我想这是因为POST是由Spring安全过滤器处理的,它是Servlet过滤器,位于主要的Spring MVC调度程序servlet之上。

我还尝试创建一个ControllerAdvice来处理SimpleMappingExceptionResolver并重定向到登录页面,但这并不是因为我的CommunicationException没有&也可以被召唤。

我提出的其他解决方法是在错误页面本身处理异常,例如(使用Thymeleaf)

SimpleMappingExceptionResolver

我仍然觉得应该有更好的方法。如何配置DispatcherServlet以确保将CommunicationException重定向到/ login控制器,而不是错误页面?或者更一般地说......如何在登录阶段配置登录阶段的任何异常?

1 个答案:

答案 0 :(得分:0)

遇到了相同的问题,并通过创建自定义Spring AuthenticationFailureHandler解决了该问题。它通过在自定义AuthenticationProvider类中抛出BadCredentialsException来捕获错误。