我有Spring Security的LDAP認證並在我們的應用程序運行,一切順利與它從一個側面運行,分開。如果AD服務器恰好處於脫機狀態或不可接觸狀態,則會觸發 ,則會引發org.springframework.ldap.CommunicationException。然而,這個異常沒有被捕獲到,並作爲一個包含堆棧跟蹤的Tomcat HTTP 500錯誤頁面(如下所示)傳播回客戶端。春季安全 - 無法趕上LDAP異常,當AD服務器脫機
我用java配置使用Spring Security 4.0.1,Java的8和Tomcat 7.0.42。
springframework.ldap.CommunicationException: localhost:389; nested exception is javax.naming.CommunicationException: localhost:389 [Root exception is java.net.ConnectException: Connection refused: connect]
org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:108)
org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.bindAsUser(ActiveDirectoryLdapAuthenticationProvider.java:211)
org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.doAuthentication(ActiveDirectoryLdapAuthenticationProvider.java:143)
org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:82)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:93)
... other frames omitted
有沒有我們在這個異常跟蹤代碼,甚至進一步上漲的堆棧(我已經爲了簡明扼要省略,因爲它只是在Servlet過濾器鏈)。
通常情況下,我只是繼承Spring ActiveDirectoryLdapAuthenticationProvider類的子類,並在該派生類中調用try/catch中的基類doAuthentication()方法並從那裏繼續。不幸的是ActiveDirectoryLdapAuthenticationProvider被宣佈爲 作爲final,所以我不能這樣做。
我試圖嘗試捕獲該異常在我的代碼嘗試了一些其他的東西。這些是
添加了一個身份驗證失敗者的formLogin配置如下。但是,這並沒有得到當異常得到投擲叫,似乎只 火基於認證例外,
... .formLogin() .usernameParameter("j_username") .passwordParameter("j_password") .loginPage("/login.jsp") .loginProcessingUrl("/j_spring_security_check") .successHandler(authenticationSuccessHandler()) .failureHandler(authenticationFailureHandler()) .and() ...
搭建authenticationEndpoint與我SecurityConfig下面的代碼的任何未通過認證的請求。 Java文件,
... .formLogin() .usernameParameter("j_username") .passwordParameter("j_password") .loginPage("/login.jsp") .loginProcessingUrl("/j_spring_security_check") .successHandler(authenticationSuccessHandler()) .and() .exceptionHandling().authenticationEntryPoint(myAuthenticationEntryPoint()) ...
其中myAuthenticationEntryPoint()方法是,僅僅返回一個新Http403ForbiddenEntryPoint一個@Bean批註的方法。但是,這不會被稱爲 ,我仍然收到HTTP 500錯誤,而不是來自配置的身份驗證入口點的403錯誤。
如下所示拋出在Spring Security的源代碼異常的實際方法:
private DirContext bindAsUser(String username, String password) {
// TODO. add DNS lookup based on domain
final String bindUrl = url;
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String bindPrincipal = createBindPrincipal(username);
env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
env.put(Context.PROVIDER_URL, bindUrl);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.OBJECT_FACTORIES, DefaultDirObjectFactory.class.getName());
try {
return contextFactory.createContext(env);
} catch (NamingException e) {
if ((e instanceof AuthenticationException) || (e instanceof OperationNotSupportedException)) {
handleBindException(bindPrincipal, e);
throw badCredentials(e);
} else {
throw LdapUtils.convertLdapException(e);
}
}
}
對於在AD服務器不接觸的情況下,則代碼進入在異常處理程序中的其他條款我們得到一個基於Ldap的異常。據我所見,這意味着沒有任何「正常」的身份驗證失敗處理程序被調用。
我發現捕獲這個異常的唯一方法是'fork'ActiveDirectoryLdapAuthenticationProvider類,即剪切+粘貼它的內容到一個新類中,並從中派生出一個類。這樣做可以按預期工作,我可以在try/catch中捕獲異常。但我真的不想去這個選項,因爲它只是一個黑客。
有沒有人有類似的情況,發現了一個更好的解決方案呢?我不禁想到,在登錄過程中,必須有辦法處理所有異常,而不僅僅是基於身份驗證的方式,但我一直無法找到一種方法來執行此操作。
我有同樣的問題,所以我必須實現我自己的'AuthenticationProvider',也許把自己的夜錯誤頁面在web.xml將幫助您:' \t \t \t \t /error.htm \t @ –
@DavidHerrero,謝謝你的回覆。我希望在我的配置中只有一個缺失的部分。不得不實現我自己的AuthenticationProvider來捕獲異常似乎相當重量級。不是我懷疑你在說什麼:),也許這是唯一的方法。 – user3262600
我會寫一個可以幫助你的小答案。 –