在登录的时候,往往希望记录如果登录失败者的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>
Original url: Access
Created at: 2019-06-24 12:27:35
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论