2012-07-12 98 views
4

我正在使用Spring Security 3.1爲用戶驗證網站。當因爲春季安全是無法連接到數據庫的登錄失敗,我得到下面的語句在我的日誌:Spring安全認證日誌記錄

2012-07-12 11:42:45,419 [ajp-bio-8009-exec-1] DEBUG  org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database! 

我的問題是,爲什麼這是一個DEBUG語句,而不是一個錯誤?我必須通過大量的調試語句來查找實際的錯誤。

編輯

這裏是我的認證管理器:

<bean id="securityDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" value="java:comp/env/securityDS"/> 
    <property name="resourceRef" value="true"/> 
</bean> 

<bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" /> 

<security:authentication-manager> 
    <security:authentication-provider> 
     <security:password-encoder ref="encoder" /> 
     <security:jdbc-user-service 
      data-source-ref="securityDataSource" 
      authorities-by-username-query="SELECT username, authority FROM login WHERE username = ?" 
      users-by-username-query="SELECT username, password, enabled FROM login WHERE username = ?" 
     />   
    </security:authentication-provider> 
</security:authentication-manager> 

回答

7

這消息在AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication打印出來:

protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, 
     AuthenticationException failed) throws IOException, ServletException { 
    SecurityContextHolder.clearContext(); 

    if (logger.isDebugEnabled()) { 
     logger.debug("Authentication request failed: " + failed.toString()); 

有多種方式的認證可能會失敗,包括基於在用戶輸入。例如,在AbstractUserDetailsAuthenticationProvider.authenticate,一個BadCredentialsException可如果沒有找到用戶名拋出:

 try { 
      user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); 
     } catch (UsernameNotFoundException notFound) { 
      logger.debug("User '" + username + "' not found"); 

      if (hideUserNotFoundExceptions) { 
       throw new BadCredentialsException(messages.getMessage(
         "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); 
      } else { 
       throw notFound; 
      } 
     } 

由於可能有正當理由的驗證可能會失敗,它不會爲AbstractAuthenticationProcessingFilter意義的記錄錯誤。如果出現系統錯誤,則應該在下游記錄錯誤。

我懷疑問題是DaoAuthenticationProvider(見我的評論在線):

protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) 
     throws AuthenticationException { 
    UserDetails loadedUser; 

    try { 
     loadedUser = this.getUserDetailsService().loadUserByUsername(username); 
    } 
    catch (DataAccessException repositoryProblem) { 
     // *** ERROR SHOULD BE LOGGED HERE *** 
     throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); 
    } 

也許一個錯誤應該被記錄在這裏 - 你可以記錄一個JIRA與Spring來請求。雖然也許他們假設每個人都會提供一個自定義UserDetailsService,並且會在那裏記錄/記錄他們自己的例外情況。如果您使用的是JdbcDaoImpl,則不會。我認爲JdbcDaoImpl只是一個例子,並不健全。每文檔:

的好消息是,我們提供了好幾個UserDetailsS​​ervice 實現,其中一個使用內存映射 (InMemoryDaoImpl),另一個使用JDBC(JdbcDaoImpl)之一。然而,大多數用戶 傾向於編寫他們自己的,而他們的實現通常僅僅是在 應用程序代表其僱員,客戶或其他用戶的現有數據訪問對象(DAO)之上。

+0

如何找出我正在使用的UserDetailService類型? – 2012-07-13 13:25:06

+0

你可以發佈你的配置的''部分嗎? – sourcedelica 2012-07-13 15:09:31

+0

問題已更新。 – 2012-07-13 15:25:15

13

我的解決辦法:

@Component 
public class AuthenticationEventListener implements ApplicationListener<AbstractAuthenticationEvent> { 

    private static Logger logger = Logger.getLogger(AuthenticationEventListener.class); 

    @Override 
    public void onApplicationEvent(AbstractAuthenticationEvent authenticationEvent) { 
     if (authenticationEvent instanceof InteractiveAuthenticationSuccessEvent) { 
     // ignores to prevent duplicate logging with AuthenticationSuccessEvent 
     return; 
     } 
     Authentication authentication = authenticationEvent.getAuthentication(); 
     String auditMessage = "Login attempt with username: " + authentication.getName() + "\t\tSuccess: " + authentication.isAuthenticated(); 
     logger.info(auditMessage); 
    } 

} 

沒有其他配置是必需的。

+0

你在配置中添加AuthenticationEventListener的位置?它是否必須構建到主Web應用程序jar文件中? – whatnick 2015-01-21 04:32:24

+1

我已成功使用這樣的使用記錄儀使用JDBC: 的 \t <屬性名= 「數據源」> \t \t \t whatnick 2015-01-22 05:20:14