prevent brute force authentications

This commit is contained in:
DOHA 2015-02-13 18:08:47 +02:00
parent 54bf8b0e1c
commit aaabca5d2a
9 changed files with 117 additions and 3 deletions

View File

@ -2,6 +2,7 @@ package org.baeldung.persistence.model;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@ -23,6 +24,7 @@ public class User {
private String email;
@Column(length = 60)
private String password;
private boolean enabled;

View File

@ -0,0 +1,19 @@
package org.baeldung.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
@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());
}
}

View File

@ -0,0 +1,19 @@
package org.baeldung.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
@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());
}
}

View File

@ -0,0 +1,49 @@
package org.baeldung.security;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Service;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@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;
}
}
}

View File

@ -5,6 +5,8 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.baeldung.persistence.dao.RoleRepository;
import org.baeldung.persistence.dao.UserRepository;
import org.baeldung.persistence.model.Privilege;
@ -34,6 +36,12 @@ public class MyUserDetailsService implements UserDetailsService {
@Autowired
private RoleRepository roleRepository;
@Autowired
private LoginAttemptService loginAttemptService;
@Autowired
private HttpServletRequest request;
public MyUserDetailsService() {
super();
}
@ -42,6 +50,11 @@ public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException {
String ip = request.getRemoteAddr();
if (loginAttemptService.isBlocked(ip)) {
throw new RuntimeException("blocked");
}
try {
final User user = userRepository.findByEmail(email);
if (user == null) {

View File

@ -59,3 +59,4 @@ message.forgetPassword=Forget Password
message.resetPassword=Reset Password
message.updatePassword=Update Password
message.userNotFound=User Not Found
auth.message.blocked=This ip is blocked for 24 hours

View File

@ -59,3 +59,4 @@ message.forgetPassword=Olvide la contrase
message.resetPassword=Restablecer contraseña
message.updatePassword=Actualizar contraseña
message.userNotFound=Usuario no encontrado
auth.message.blocked=Esta IP se bloquea durante 24 horas

View File

@ -20,6 +20,12 @@
<div class="alert alert-error">
<spring:message code="auth.message.expired"></spring:message>
</div>
</c:when>
<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>
<c:otherwise>
<div class="alert alert-error">

View File

@ -17,6 +17,10 @@
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>