转载

spring security中限制用户登录次数超过限制的处理

在登录的时候,往往希望记录如果登录失败者的ip,并且登录失败次数超过一定的,则不给登录,予以封锁。在spring security中,可以通过如下方式实现。

1) 实现AuthenticationFailureEventListener,这个监听器用来监听

登录失败的事件。

@Component public class AuthenticationFailureListener    implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {  @Autowired  private LoginAttemptService loginAttemptService;  public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) {   WebAuthenticationDetails auth = (WebAuthenticationDetails)      e.getAuthentication().getDetails();   loginAttemptService.loginFailed(auth.getRemoteAddress());  } } 

2) 同样有登录成功的监听

AuthenticationSuccessEventListener,

@Component public class AuthenticationSuccessEventListener    implements ApplicationListener<AuthenticationSuccessEvent> {  @Autowired  private LoginAttemptService loginAttemptService;  public void onApplicationEvent(AuthenticationSuccessEvent e) {   WebAuthenticationDetails auth = (WebAuthenticationDetails)      e.getAuthentication().getDetails();   loginAttemptService.loginSucceeded(auth.getRemoteAddress());  } } 

3) LoginAttemptService中,主要是通过缓存记录登录失败次数等,十分简单

@Service public class LoginAttemptService {  private final int MAX_ATTEMPT = 10;  private LoadingCache<String, Integer> attemptsCache;  public LoginAttemptService() {   super();   attemptsCache = CacheBuilder.newBuilder().     expireAfterWrite(1, TimeUnit.DAYS).build(new CacheLoader<String, Integer>() {    public Integer load(String key) {     return 0;    }   });  }  public void loginSucceeded(String key) {   attemptsCache.invalidate(key);  }  public void loginFailed(String key) {   int attempts = 0;   try {    attempts = attemptsCache.get(key);   } catch (ExecutionException e) {    attempts = 0;   }   attempts++;   attemptsCache.put(key, attempts);  }  public boolean isBlocked(String key) {   try {    return attemptsCache.get(key) >= MAX_ATTEMPT;   } catch (ExecutionException e) {    return false;   }  } } 

4) 最后在userdetailService类中,修改下

@Service("userDetailsService") @Transactional public class MyUserDetailsService implements UserDetailsService {  @Autowired  private UserRepository userRepository;  @Autowired  private RoleRepository roleRepository;  @Autowired  private LoginAttemptService loginAttemptService;  @Autowired  private HttpServletRequest request;  @Override  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {   String ip = request.getRemoteAddr();   if (loginAttemptService.isBlocked(ip)) {    throw new RuntimeException("blocked");   }   try {     ................ } 

5) 注意这里修改下web.xml,因为loadUserByUsername中要获得ip

<listener>

<listener-class>

org.springframework.web.context.request.RequestContextListener

</listener-class>

</listener>

6) 前端jsp页面适当修改

<c:when test="${SPRING_SECURITY_LAST_EXCEPTION.message == 'blocked'}">

<div class="alert alert-error">

<spring:message code="auth.message.blocked"></spring:message>

</div>

</c:when>

已有 0 人发表留言,猛击->> 这里 <<-参与讨论

ITeye推荐

  • —软件人才免语言低担保 赴美带薪读研!—
正文到此结束
Loading...