Checking Account Lock-out
The first bit of code I need to inject into this method is to check to see whether the account is locked out. Because this is a rather quick check, I want to complete it before getting into anything else that would be unnecessary if the account is locked. Therefore, I will add the check to the very top of the method. Therefore, the top of the method is changed to this:
public boolean login() throws LoginException { if (getCounter() > maxRetries) { super.loginOk = false; throw new FailedLoginException("Account Locked"); }
This snippet of code relies on two methods to be added to the class. The first method retrieves the current number of failed login attempts for the current account. The code to handle that is detailed here:
private int getCounter() { String username = getUsername(); Connection con = null; try { InitialContext ic = new InitialContext(); DataSource ds = (DataSource) ic.lookup(dsJndiName); con = ds.getConnection(); PreparedStatement ps = con.prepareStatement(getCounterQuery); ps.setString(1, username); ResultSet rs = ps.executeQuery(); if (rs.next()) { int counter = rs.getInt(1); return counter; } else { return Integer.MAX_VALUE; } } catch (NamingException e) { _log.error("Unexpected error", e); return Integer.MAX_VALUE; } catch (SQLException e) { _log.error("Query failed", e); return Integer.MAX_VALUE; } finally { try { if (con != null) { con.close(); } } catch (Throwable e) { _log.error("Error closing connection", e); } } }
This new method also relies on some global variables that are not yet present. These global variables will be initialized in the init() method (discussed later in this article) for reasons that will become apparent.
Another item to note is the use of a DataSource instead of connecting to the database directly. Because this code will be running within the application server's JVM, it gets access to all the data sources initialized inside of the application.