Logging User Activity
The next modification requires another private method to be created that will be used several times through the login method. The requirement to log every failed attempt requires the following method:
private void logAttempt(boolean failed) { String username = getUsername(); Connection con = null; try { InitialContext ic = new InitalContext(); DataSource ds = (DataASource)ic.lookup(dsJndiName); con = ds.getConnection(); PreparedStatement ps = con.prepareStatement(logQuery); ps.setString(1, username); ps.setTimestamp(2, new Timestamp(System.currentTimeMillis())); ps.setString(3, (failed?"Login Failed","Login Successful")); ps.executeUpdate(); if (failed) incrementCounter(); } catch (Exception e) { _log.error("Unexpected error", e); } finally { if (con != null) { try { con.close(); } catch (Throwable e) { _log.error("Error closing connection", e); } } } }
I passed in a boolean to tell this method whether or not it is logging a successful or failed attempt, which allows me to utilize this method for both situations. With the logging method build, it is simple to inject a call to this method just before every exception is thrown. The code for this change will be listed at the end of the article in the completed class' source code.
For the login attempt counter to function properly, it needs to be incremented every time there is a failed login. As shown in the method above, the final action after the login attempt is logged is to check whether it is a failed login—and if so to increment the counter. The code to increment the counter is as follows:
private void incrementCounter() { String username = getUsername(); Connection con = null; try { InitialContext ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup(dsJndiName); con = ds.getConnection(); PreparedStatement ps = con.prepareStatement(incrementCounterQuery); ps.setString(1, username); ps.executeUpdate(); } catch (NamingException e) { _log.error("Unexpected error", e); } catch (SQLException e) { _log.error("Query failed", e); } finally { try { if (con != null) { con.close(); } } catch (Throwable e) { _log.error("Error closing connection", e); } } }