← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 1567: Impl logging of authentication failures through an ApplicationListener. Moved logging of authenti...

 

------------------------------------------------------------
revno: 1567
committer: Lars Helge Oeverland <larshelge@xxxxxxxxx>
branch nick: trunk
timestamp: Sat 2010-03-06 18:02:42 +0100
message:
  Impl logging of authentication failures through an ApplicationListener. Moved logging of authentication successes to the same listener. Spring Security emits handy ApplicationEvents for authentication success and failure which are now used for detection. Minor re-factor, renamed FailedLogin to LoginFailure.
added:
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener/
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener/AuthenticationListener.java
renamed:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/FailedLogin.java => dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/LoginFailure.java
  dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/FailedLogin.hbm.xml => dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/LoginFailure.hbm.xml
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditStore.java
  dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/DefaultUserAuditService.java
  dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/hibernate/HibernateUserAuditStore.java
  dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/useraudit/UserAuditStoreTest.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/action/LoggedInAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/LoginFailure.java
  dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/LoginFailure.hbm.xml


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription.
=== renamed file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/FailedLogin.java' => 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/LoginFailure.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/FailedLogin.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/LoginFailure.java	2010-03-06 17:02:42 +0000
@@ -2,7 +2,7 @@
 
 import java.util.Date;
 
-public class FailedLogin
+public class LoginFailure
 {
     private int id;
     
@@ -10,11 +10,11 @@
     
     private Date date;
     
-    public FailedLogin()
+    public LoginFailure()
     {
     }
     
-    public FailedLogin( String username, Date date )
+    public LoginFailure( String username, Date date )
     {
         this.username = username;
         this.date = date;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditService.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditService.java	2010-03-06 17:02:42 +0000
@@ -5,9 +5,9 @@
     final int TIMEFRAME_NUMBER_OF_HOURS = 1;
     final int MAX_NUMBER_OF_ATTEMPTS = 3;
     
-    void registerLogin( String username );
+    void registerLoginSuccess( String username );
     
     void registerLogout( String username );
     
-    void registerLoginFailed( String username );
+    void registerLoginFailure( String username );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditStore.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/useraudit/UserAuditStore.java	2010-03-06 17:02:42 +0000
@@ -7,9 +7,11 @@
 {
     final String ID = UserAuditStore.class.getName();
     
-    void saveFailedLogin( FailedLogin login );
-    
-    Collection<FailedLogin> getAllFailedLogins();
-    
-    int getFailedLogins( String username, Date date );
+    void saveLoginFailure( LoginFailure login );
+    
+    Collection<LoginFailure> getAllLoginFailures();
+    
+    void deleteLoginFailures( String username );
+    
+    int getLoginFailures( String username, Date date );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/DefaultUserAuditService.java'
--- dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/DefaultUserAuditService.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/DefaultUserAuditService.java	2010-03-06 17:02:42 +0000
@@ -5,6 +5,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.springframework.transaction.annotation.Transactional;
 
 public class DefaultUserAuditService
     implements UserAuditService
@@ -18,9 +19,9 @@
         this.userAuditStore = userAuditStore;
     }
 
-    public void registerLogin( String username )
+    public void registerLoginSuccess( String username )
     {
-        log.info( "User login: '" + username + "'" );        
+        log.info( "User login success: '" + username + "'" );        
     }
 
     public void registerLogout( String username )
@@ -28,17 +29,20 @@
         log.info( "User logout: '" + username + "'" );
     }
 
-    public void registerLoginFailed( String username )
+    @Transactional
+    public void registerLoginFailure( String username )
     {
-        log.info( "User login failed: '" + username + "'" );
-        
-        userAuditStore.saveFailedLogin( new FailedLogin( username, new Date() ) );
-        
-        int no = userAuditStore.getFailedLogins( username, getDate() );
-        
-        if ( no > MAX_NUMBER_OF_ATTEMPTS )
+        log.info( "User login failure: '" + username + "'" );
+        
+        userAuditStore.saveLoginFailure( new LoginFailure( username, new Date() ) );
+        
+        int no = userAuditStore.getLoginFailures( username, getDate() );
+        
+        if ( no >= MAX_NUMBER_OF_ATTEMPTS )
         {
             log.info( "Max number of login attempts exceeded: '" + username + "'" );
+            
+            userAuditStore.deleteLoginFailures( username );
         }
     }
     

=== modified file 'dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/hibernate/HibernateUserAuditStore.java'
--- dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/hibernate/HibernateUserAuditStore.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/useraudit/hibernate/HibernateUserAuditStore.java	2010-03-06 17:02:42 +0000
@@ -5,7 +5,7 @@
 
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
-import org.hisp.dhis.useraudit.FailedLogin;
+import org.hisp.dhis.useraudit.LoginFailure;
 import org.hisp.dhis.useraudit.UserAuditStore;
 
 public class HibernateUserAuditStore
@@ -18,26 +18,33 @@
         this.sessionFactory = sessionFactory;
     }
 
-    public void saveFailedLogin( FailedLogin login )
+    public void saveLoginFailure( LoginFailure login )
     {
         sessionFactory.getCurrentSession().save( login );
     }
     
     @SuppressWarnings( "unchecked" )
-    public Collection<FailedLogin> getAllFailedLogins()
+    public Collection<LoginFailure> getAllLoginFailures()
     {
-        return sessionFactory.getCurrentSession().createCriteria( FailedLogin.class ).list();
+        return sessionFactory.getCurrentSession().createCriteria( LoginFailure.class ).list();
     }
     
-    public int getFailedLogins( String username, Date date )
+    public void deleteLoginFailures( String username )
+    {
+        String hql = "delete from LoginFailure where username = :username";
+        
+        sessionFactory.getCurrentSession().createQuery( hql ).setString( "username", username ).executeUpdate();
+    }
+        
+    public int getLoginFailures( String username, Date date )
     {
         Session session = sessionFactory.getCurrentSession();
         
-        String hql = "delete from FailedLogin where date < :date";
+        String hql = "delete from LoginFailure where date < :date";
         
         session.createQuery( hql ).setDate( "date", date ).executeUpdate();
         
-        hql = "select count(*) from FailedLogin where username = :username";
+        hql = "select count(*) from LoginFailure where username = :username";
         
         Long no = (Long) session.createQuery( hql ).setString( "username", username ).uniqueResult();
         

=== renamed file 'dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/FailedLogin.hbm.xml' => 'dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/LoginFailure.hbm.xml'
--- dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/FailedLogin.hbm.xml	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-services/dhis-service-administration/src/main/resources/org/hisp/dhis/useraudit/hibernate/LoginFailure.hbm.xml	2010-03-06 17:02:42 +0000
@@ -4,8 +4,8 @@
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
 
 <hibernate-mapping>
-  <class name="org.hisp.dhis.useraudit.FailedLogin" table="failedlogin">
-    <id name="id" column="failedloginid">
+  <class name="org.hisp.dhis.useraudit.LoginFailure" table="loginfailure">
+    <id name="id" column="loginfailureid">
       <generator class="native"/>
     </id>        
     <property name="username"/>

=== modified file 'dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/useraudit/UserAuditStoreTest.java'
--- dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/useraudit/UserAuditStoreTest.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/useraudit/UserAuditStoreTest.java	2010-03-06 17:02:42 +0000
@@ -19,23 +19,23 @@
     @Test
     public void save()
     {
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 3 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 4 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userB", getDate( 2000, 1, 5 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 3 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 4 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userB", getDate( 2000, 1, 5 ) ) );
         
-        assertNotNull( userAuditStore.getAllFailedLogins() );
-        assertEquals( 3, userAuditStore.getAllFailedLogins().size() );
+        assertNotNull( userAuditStore.getAllLoginFailures() );
+        assertEquals( 3, userAuditStore.getAllLoginFailures().size() );
     }
     
     @Test
     public void get()
     {
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 3 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 4 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 5 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userA", getDate( 2000, 1, 6 ) ) );
-        userAuditStore.saveFailedLogin( new FailedLogin( "userB", getDate( 2000, 1, 7 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 3 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 4 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 5 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userA", getDate( 2000, 1, 6 ) ) );
+        userAuditStore.saveLoginFailure( new LoginFailure( "userB", getDate( 2000, 1, 7 ) ) );
         
-        assertEquals( 3, userAuditStore.getFailedLogins( "userA", getDate( 2000, 1, 4 ) ) );
+        assertEquals( 3, userAuditStore.getLoginFailures( "userA", getDate( 2000, 1, 4 ) ) );
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/action/LoggedInAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/action/LoggedInAction.java	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/action/LoggedInAction.java	2010-03-06 17:02:42 +0000
@@ -33,8 +33,7 @@
 import org.hisp.dhis.oust.manager.SelectionTreeManager;
 import org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager;
 import org.hisp.dhis.user.CurrentUserService;
-import org.hisp.dhis.useraudit.UserAuditService;
-import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
+import org.hisp.dhis.user.User;
 
 import com.opensymphony.xwork2.Action;
 
@@ -70,13 +69,6 @@
         this.currentUserService = currentUserService;
     }
     
-    private UserAuditService userAuditService;
-
-    public void setUserAuditService( UserAuditService userAuditService )
-    {
-        this.userAuditService = userAuditService;
-    }
-
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -84,21 +76,15 @@
     public String execute()
         throws Exception
     {
-        String username = currentUserService.getCurrentUsername();
+        User user = currentUserService.getCurrentUser();
         
-        if ( username != null )
+        if ( user != null )
         {
             // -----------------------------------------------------------------
-            // Register login
-            // -----------------------------------------------------------------
-
-            userAuditService.registerLogin( username );
-
-            // -----------------------------------------------------------------
             // Initialize ouwt and selection tree
             // -----------------------------------------------------------------
 
-            Collection<OrganisationUnit> orgUnits = currentUserService.getCurrentUser().getOrganisationUnits();
+            Collection<OrganisationUnit> orgUnits = user.getOrganisationUnits();
 
             if ( orgUnits.size() > 0 )
             {

=== added directory 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener'
=== added file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener/AuthenticationListener.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener/AuthenticationListener.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/listener/AuthenticationListener.java	2010-03-06 17:02:42 +0000
@@ -0,0 +1,35 @@
+package org.hisp.dhis.security.listener;
+
+import org.hisp.dhis.useraudit.UserAuditService;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.security.event.authentication.AbstractAuthenticationFailureEvent;
+import org.springframework.security.event.authentication.AuthenticationSuccessEvent;
+import org.springframework.security.userdetails.UserDetails;
+
+public class AuthenticationListener
+    implements ApplicationListener
+{
+    private UserAuditService userAuditService;
+    
+    public void setUserAuditService( UserAuditService userAuditService )
+    {
+        this.userAuditService = userAuditService;
+    }
+
+    public void onApplicationEvent( ApplicationEvent applicationEvent )
+    {        
+        if ( applicationEvent != null && applicationEvent instanceof AuthenticationSuccessEvent )
+        {
+            AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) applicationEvent;
+            
+            userAuditService.registerLoginSuccess( ((UserDetails) event.getAuthentication().getPrincipal()).getUsername() );
+        }
+        else if ( applicationEvent != null && applicationEvent instanceof AbstractAuthenticationFailureEvent )
+        {
+            AbstractAuthenticationFailureEvent event = (AbstractAuthenticationFailureEvent) applicationEvent;
+            
+            userAuditService.registerLoginFailure( (String) event.getAuthentication().getPrincipal() );
+        }
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2010-03-06 16:00:25 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2010-03-06 17:02:42 +0000
@@ -268,8 +268,6 @@
 			ref="org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager" />
 		<property name="selectionTreeManager"
 			ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
-		<property name="userAuditService"
-			ref="org.hisp.dhis.useraudit.UserAuditService" />
 	</bean>
 		
     <!-- Security : Filter -->
@@ -319,6 +317,12 @@
         <property name="loginPageUrl" value="/dhis-web-commons/security/login.html" />
     </bean>
 
+    <!-- Security : Listener -->
+	
+    <bean id="authenticationListener" class="org.hisp.dhis.security.listener.AuthenticationListener">       
+        <property name="userAuditService" ref="org.hisp.dhis.useraudit.UserAuditService" />
+    </bean>
+    
     <!-- Security : AccessProvider -->
     
 	<bean id="databaseAutomaticAccessProvider" class="org.hisp.dhis.security.DatabaseAutomaticAccessProvider">