Spring Security:如何实现蛮力检测(BFD)?

我的Web应用程序安全性由Spring Security 3.02处理,但我找不到任何对蛮力检测的开箱即用支持。

我想实现一些应用程序级BFD保护。例如,通过在数据库中存储每个用户的失败登录尝试 (JPA)。然后,受攻击的用户帐户可能会通过电子邮件获得锁定期或强制重新激活帐户。

使用Spring Security实现这一点的最佳方法是什么?是否有任何机构在这方面有示例代码或最佳实践?


答案 1

滚动自己的BFD并不难。与Spring Security 3.0一样,您可以简单地添加应用程序侦听器(感谢Stephen C为我指出了正确的方向)。

当出现身份验证失败时,将调用此侦听器:

@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();
    }
  }
}

现在,每次身份验证失败都会通知用户。例如,用户递增身份验证失败计数器,并在达到特定阈值时自行停用它。

当用户正确通过身份验证时,以下侦听器将通知用户(例如,用户可以重置其身份验证失败计数器):

@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();
  }
}

上述侦听器不需要额外的XML配置,并且由Spring自动拾取(如果它们在Spring组件扫描包中)。

根据您的事务配置,如果某些失败的登录计数几乎同时发生,此解决方案可能会错过它们。如果使用单个 UPDATE 查询更新计数器,而不是加载用户,然后保存更改,则可以防止出现这种情况。

上述侦听器还可以扩展以检测其他BDF模式,例如,对大量(随机)用户名进行扫描的单个IP。


答案 2

您还应该知道,锁定受攻击的帐户意味着使您的服务可执行。

众所周知的例子是:您提供拍卖服务,鲍勃想要购买一些头寸并攻击爱丽丝的帐户,因此爱丽丝没有下注,而是试图在鲍勃获得头寸时恢复她的帐户。即使是临时(5 秒)锁定也可能阻止 Alice 根据需要使用该服务。