It's not that hard to role you're own BFD. As in Spring Security 3.0 you can simply add Application listeners (thanks Stephen C for pointing me in the correct direction).
This listener will be called when authentication failures appear:
@Component
public class AuthenticationFailureListener
implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
@Autowired
private UserDao userDao;
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent ev) {
String username = ev.getAuthentication().getName();
User user = userDao.find("name", username);
if (user != null) { // only for existing users
user.reportLoginFailure();
userDao.commit();
}
}
}
Each authentication failure will now inform the user. The user for example increments an authentication failure counter and deactivates it self when a certain threshold is reached.
When a user is correctly authenticated the below listener will inform the user (who for example can reset it’s authentication failure counters):
@Component
public class AuthenticationSuccessEventListener
implements ApplicationListener<AuthenticationSuccessEvent>{
@Autowired
private UserDao userDao;
public void onApplicationEvent(AuthenticationSuccessEvent event) {
String username = event.getAuthentication().getName();
User user = userDao.find("name", username);
user.reportLoginOK();
userDao.commit();
}
}
The above listeners will not need additional XML configuration and are picked up automatically by Spring (if they are in Spring component-scan package).
Depending on you transaction configuration this solution could miss some failed login counts if they happen near simultaneously. This can be prevented if you update the counter with a single UPDATE query instead of loading the user and then save the changes.
Above listeners can also be extended to detect other BDF patterns, for example a single IP that is doing a scan on lot’s of (random) user names.