在登录的时候,往往希望记录如果登录失败者的ip,并且登录失败次数超过一定的,则不给登录,予以封锁。在spring security中,可以通过如下方式实现。
1) 实现AuthenticationFailureEventListener,这个监听器用来监听
登录失败的事件。
2) 同样有登录成功的监听
AuthenticationSuccessEventListener,
3) LoginAttemptService中,主要是通过缓存记录登录失败次数等,十分简单
4) 最后在userdetailService类中,修改下
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推荐
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推荐