STEP 1:- To perform database authentication, you have to create tables to store the users and roles detail.
Here are the MySQL scripts to create users and user_roles tables.
STEP 3:- Make sure you use Target Runtime as Apache Tomcat 7.0 and Dynamic web module version as 3.0..
STEP 4:- copy below jars to WEB-INF/lib folder.
http://localhost:8080/SpringSecurityLimitLoginAttemptJavaConfig/
Keep visiting TutorialsDesk for more tutorials and practical programming examples on Spring MVC. Hope we are able to explain you Spring MVC security limit login attempts example using Java configuration Example, if you have any questions or suggestions please write to us using contact us form.
Please share us on social media if you like the tutorial.
- Table: users
CREATE TABLE users ( username VARCHAR(60) NOT NULL , password VARCHAR(60) NOT NULL , enabled TINYINT NOT NULL DEFAULT 1 , accountNonExpired TINYINT NOT NULL DEFAULT 1 , accountNonLocked TINYINT NOT NULL DEFAULT 1 , credentialsNonExpired TINYINT NOT NULL DEFAULT 1 , PRIMARY KEY (username));
- Table: user_roles
CREATE TABLE user_roles ( user_role_id int(11) NOT NULL AUTO_INCREMENT, username varchar(60) NOT NULL, role varchar(60) NOT NULL, PRIMARY KEY (user_role_id), UNIQUE KEY uni_username_role (role,username), KEY fk_username_idx (username), CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username));
- Table: user_attempts
CREATE TABLE user_attempts ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(45) NOT NULL, attempts varchar(45) NOT NULL, lastModified datetime NOT NULL, PRIMARY KEY (id) );
- here is insert script
insert into users values('user','123456',1) insert into users values('apiuser','123456',1) insert into users values('admin','123456',1) insert into user_roles values('user','ROLE_USER') insert into user_roles values('admin','ROLE_USER') insert into user_roles values('admin','ROLE_ADMIN') insert into user_roles values('admin','ROLE_API') insert into user_roles values('apiuser','ROLE_USER') insert into user_roles values('apiuser','ROLE_API')STEP 2:- Open Eclipse and Create Dynamic Web Project named SpringSecurityLimitLoginAttemptJavaConfig
STEP 3:- Make sure you use Target Runtime as Apache Tomcat 7.0 and Dynamic web module version as 3.0..
STEP 4:- copy below jars to WEB-INF/lib folder.
- antlr-2.7.6.jar
- aopalliance-1.0.jar
- commons-logging-1.2.jar
- dom4j-1.6.1.jar
- hibernate-commons-annotations-4.0.4.Final.jar
- hibernate-core-4.3.6.Final.jar
- hibernate-jpa-2.1-api-1.0.0.Final.jar
- hibernate-validator-4.3.2.Final.jar
- javassist-3.12.1.GA.jar
- jboss-logging-3.1.0.CR1.jar
- jta.jar
- jtds.jar
- persistence-api-1.0.2.jar
- spring-aop-4.1.4.RELEASE.jar
- spring-aspects-4.1.4.RELEASE.jar
- spring-beans-4.1.4.RELEASE.jar
- spring-context-4.1.4.RELEASE.jar
- spring-core-4.1.4.RELEASE.jar
- spring-expression-4.1.4.RELEASE.jar
- spring-jdbc-4.1.4.RELEASE.jar
- spring-orm-4.1.4.RELEASE.jar
- spring-security-config-4.0.2.RELEASE.jar
- spring-security-core-4.0.2.RELEASE.jar
- spring-security-taglibs-4.0.2.RELEASE.jar
- spring-security-web-4.0.2.RELEASE.jar
- spring-tx-4.1.4.RELEASE.jar
- spring-web-4.1.4.RELEASE.jar
- spring-webmvc-4.1.4.RELEASE.jar
- Package: com.tutorialsdesk.config
- Filename: DataSourceConfig.java
package com.tutorialsdesk.config; import java.util.Properties; import javax.annotation.Resource; import javax.sql.DataSource; import org.hibernate.SessionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableTransactionManagement public class DataSourceConfig { private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver"; private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password"; private static final String PROPERTY_NAME_DATABASE_URL = "db.jdbcurl"; private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username"; @Resource private Environment env; @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER)); dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL)); dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME)); dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD)); return dataSource; } @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource()); builder.scanPackages("com.tutorialsdesk.model").addProperties(getHibernateProperties()); return builder.buildSessionFactory(); } private Properties getHibernateProperties() { Properties prop = new Properties(); prop.put("hibernate.format_sql", "true"); prop.put("hibernate.show_sql", "true"); prop.put("hibernate.connection.pool_size", "5"); prop.put("hibernate.hbm2ddl.auto", "update"); prop.put("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect"); return prop; } @Bean public HibernateTransactionManager transactionManager() { return new HibernateTransactionManager(sessionFactory()); } }STEP 6:- Create db.properties file under WEB-INF/db.properties.
db.driver=com.mysql.jdbc.Driver db.jdbcurl=jdbc:mysql://localhost:3306/test db.username=root db.password=passwordSTEP 7:- Create Spring Security configuration fileas below.
- Package: com.tutorialsdesk.config
- Filename: SecurityConfig.java
package com.tutorialsdesk.config; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import com.tutorialsdesk.service.CustomUsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired @Qualifier("authenticationProvider") AuthenticationProvider authenticationProvider; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/home").access("hasRole('ROLE_USER')") .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") .antMatchers("/api/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_API')") .and() .formLogin() .loginProcessingUrl("/login") .loginPage("/loginPage") .failureUrl("/loginPage?error") .defaultSuccessUrl("/home") .usernameParameter("username") .passwordParameter("password") .and() .exceptionHandling() .accessDeniedPage("/Access_Denied"); } }STEP 8:- Create a class extends AbstractSecurityWebApplicationInitializer, it will load the springSecurityFilterChain automatically.
- Package: com.tutorialsdesk.config.core
- Filename: SpringSecurityInitializer.java
package com.tutorialsdesk.config.core; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer { }STEP 9:- Create Spring MVC configuration file. A Config class, define the view’s technology and imports above DataSourceConfig and SecurityConfig.
- Package: com.tutorialsdesk.config
- Filename: WebMvcConfig.java
package com.tutorialsdesk.config; import javax.annotation.Resource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @EnableWebMvc @Configuration @ComponentScan({ "com.tutorialsdesk.controller","com.tutorialsdesk.service","com.tutorialsdesk.dao.impl","com.tutorialsdesk.service.impl","com.tutorialsdesk.handler" }) @Import({ SecurityConfig.class, DataSourceConfig.class }) @PropertySource("/WEB-INF/db.properties") public class WebMvcConfig { @Resource private Environment env; @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } }STEP 10:- Create a Sevlet Initializer class, to load everything.
- Package: com.tutorialsdesk.config.core
- Filename: SpringMvcInitializer.java
package com.tutorialsdesk.config.core; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.tutorialsdesk.config.AppConfig; public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { WebMvcConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }STEP 11 :- Create Controller Class.
- Package: com.tutorialsdesk.controller
- Filename: HelloWorldController.java
package com.tutorialsdesk.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.LockedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class HelloWorldController { @RequestMapping(value = { "/", "/loginPage" }, method = RequestMethod.GET) public String loginPage(ModelMap model, @RequestParam(value = "error", required = false) String error, HttpServletRequest request) { if (error != null) { model.addAttribute("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION")); } return "login"; } @RequestMapping(value = { "/home" }, method = RequestMethod.GET) public String homePage(ModelMap model) { model.addAttribute("greeting", "Hi, Welcome to mysite. "); return "welcome"; } @RequestMapping(value = "/admin", method = RequestMethod.GET) public String adminPage(ModelMap model) { model.addAttribute("user", getPrincipal()); return "admin"; } @RequestMapping(value = "/api", method = RequestMethod.GET) public String dbaPage(ModelMap model) { model.addAttribute("user", getPrincipal()); return "api"; } @RequestMapping(value="/logout", method = RequestMethod.GET) public String logoutPage (ModelMap model,HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null){ new SecurityContextLogoutHandler().logout(request, response, auth); } model.addAttribute("msg", "You've been logged out successfully."); return "login"; } @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET) public String accessDeniedPage(ModelMap model) { model.addAttribute("user", getPrincipal()); return "accessDenied"; } private String getPrincipal(){ String userName = null; Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { userName = ((UserDetails)principal).getUsername(); } else { userName = principal.toString(); } return userName; } private String getErrorMessage(HttpServletRequest request, String key){ Exception exception = (Exception) request.getSession().getAttribute(key); String error = ""; if (exception instanceof BadCredentialsException) { error = "Invalid username and password!"; }else if(exception instanceof LockedException) { error = exception.getMessage(); }else{ error = "Invalid username and password!"; } return error; } }STEP 12 :- Create Model Class.
- Package: com.tutorialsdesk.model
- Filename: User.java
package com.tutorialsdesk.model; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "users") public class User { private String username; private String password; private boolean enabled; private boolean accountNonExpired; private boolean accountNonLocked; private boolean credentialsNonExpired; private Set<UserRole> userRole = new HashSet<UserRole>(0); public User() { } public User(String username, String password, boolean enabled) { this.username = username; this.password = password; this.enabled = enabled; } public User(String username, String password, boolean enabled, Set<UserRole> userRole) { this.username = username; this.password = password; this.enabled = enabled; this.userRole = userRole; } @Id @Column(name = "username", unique = true, nullable = false, length = 45) public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } @Column(name = "password", nullable = false, length = 60) public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } @Column(name = "enabled", nullable = false) public boolean isEnabled() { return this.enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } @Column(name = "accountNonExpired", nullable = false) public boolean isAccountNonExpired() { return accountNonExpired; } public void setAccountNonExpired(boolean accountNonExpired) { this.accountNonExpired = accountNonExpired; } @Column(name = "accountNonLocked", nullable = false) public boolean isAccountNonLocked() { return accountNonLocked; } public void setAccountNonLocked(boolean accountNonLocked) { this.accountNonLocked = accountNonLocked; } @Column(name = "credentialsNonExpired", nullable = false) public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public void setCredentialsNonExpired(boolean credentialsNonExpired) { this.credentialsNonExpired = credentialsNonExpired; } @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") public Set<UserRole> getUserRole() { return this.userRole; } public void setUserRole(Set<UserRole> userRole) { this.userRole = userRole; } }
- Package: com.tutorialsdesk.model
- Filename: UserRole.java
package com.tutorialsdesk.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "user_roles", uniqueConstraints = @UniqueConstraint(columnNames = { "role", "username" })) public class UserRole { private Integer userRoleId; private User user; private String role; public UserRole() { } public UserRole(User user, String role) { this.user = user; this.role = role; } @Id @GenericGenerator(name="native", strategy = "native") @GeneratedValue(generator = "native") @Column(name = "user_role_id", unique = true, nullable = false) public Integer getUserRoleId() { return this.userRoleId; } public void setUserRoleId(Integer userRoleId) { this.userRoleId = userRoleId; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "username", nullable = false) public User getUser() { return this.user; } public void setUser(User user) { this.user = user; } @Column(name = "role", nullable = false, length = 45) public String getRole() { return this.role; } public void setRole(String role) { this.role = role; } }
- Package: com.tutorialsdesk.model
- Filename: UserAttempts.java
package com.tutorialsdesk.model; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "user_attempts") public class UserAttempts { @Id @GenericGenerator(name="native", strategy = "native") @GeneratedValue(generator = "native") @Column(name = "id") private int id; @Column(name = "username", unique = true, nullable = false, length = 60) private String username; @Column(name = "attempts", unique = true, nullable = false, length = 60) private int attempts; @Column(name = "lastModified") @Temporal(TemporalType.TIMESTAMP) private Date lastModified; public UserAttempts() { } public UserAttempts(String username, int attempts, Date lastModified) { super(); this.username = username; this.attempts = attempts; this.lastModified = lastModified; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAttempts() { return attempts; } public void setAttempts(int attempts) { this.attempts = attempts; } public Date getLastModified() { return lastModified; } public void setLastModified(Date lastModified) { this.lastModified = lastModified; } }STEP 13 :- Create Service Interface and Class.
- Package: com.tutorialsdesk.service
- Filename: UserService.java
package com.tutorialsdesk.service; import com.tutorialsdesk.model.User; import com.tutorialsdesk.model.UserAttempts; public interface UserService { public User findUserByName(String username); void updateFailAttempts(String username); void resetFailAttempts(String username); public UserAttempts getUserAttempts(String username); }
- Package: com.tutorialsdesk.service.impl
- Filename: UserServiceImpl.java
package com.tutorialsdesk.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.tutorialsdesk.dao.UserDao; import com.tutorialsdesk.model.User; import com.tutorialsdesk.model.UserAttempts; import com.tutorialsdesk.service.UserService; @Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User findUserByName(String username) { return userDao.findUserByName(username); } @Override public void updateFailAttempts(String username) { userDao.updateFailAttempts(username); } @Override public void resetFailAttempts(String username) { userDao.resetFailAttempts(username); } @Override public UserAttempts getUserAttempts(String username) { return userDao.getUserAttempts(username); } }STEP 14 :- Create Dao Interface and Class.
- Package: com.tutorialsdesk.dao
- Filename: UserDao.java
package com.tutorialsdesk.dao; import com.tutorialsdesk.model.User; import com.tutorialsdesk.model.UserAttempts; public interface UserDao { public User findUserByName(String username); void updateFailAttempts(String username); void resetFailAttempts(String username); public UserAttempts getUserAttempts(String username); }
- Package: com.tutorialsdesk.dao.impl
- Filename: UserDaoImpl.java
package com.tutorialsdesk.dao.impl; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.LockedException; import org.springframework.stereotype.Repository; import com.tutorialsdesk.dao.UserDao; import com.tutorialsdesk.model.User; import com.tutorialsdesk.model.UserAttempts; @Repository("userDao") public class UserDaoImpl implements UserDao { @Autowired private SessionFactory sessionFactory; private static final int MAX_ATTEMPTS = 3; @SuppressWarnings("unchecked") @Override public User findUserByName(String username) { List<User> userList = new ArrayList<User>(); userList = sessionFactory.getCurrentSession().createQuery("from User where username=?").setParameter(0, username).list(); if (userList.size() > 0) return userList.get(0); else return null; } @Override public void updateFailAttempts(String username) { UserAttempts userAttempts = getUserAttempts(username); if(userAttempts!=null){ User user = findUserByName(username); if(user!=null){ Session s = sessionFactory.openSession(); Transaction t = s.beginTransaction(); Query query = s.createQuery("UPDATE UserAttempts SET attempts=:attempts, lastModified=:lastModified WHERE id=:id"); query.setParameter("attempts", userAttempts.getAttempts() + 1); query.setParameter("lastModified", new Date()); query.setParameter("id", userAttempts.getId()); query.executeUpdate(); t.commit(); } if(userAttempts.getAttempts() >= MAX_ATTEMPTS){ Session s = sessionFactory.openSession(); Transaction t = s.beginTransaction(); Query query = s.createQuery("UPDATE User SET accountNonLocked=:accountNonLocked WHERE username=:username"); query.setParameter("accountNonLocked", false); query.setParameter("username", username); query.executeUpdate(); t.commit(); throw new LockedException("User Account is locked!"); } } else{ User user = findUserByName(username); if(user!=null){ System.out.println("UserDaoImpl.updateFailAttempts()"); UserAttempts ua = new UserAttempts(username, 1, new Date()); sessionFactory.getCurrentSession().save(ua); } } } @Override public void resetFailAttempts(String username) { UserAttempts userAttempts = getUserAttempts(username); if(userAttempts!=null){ UserAttempts ua = (UserAttempts) sessionFactory.getCurrentSession().load(UserAttempts.class, userAttempts.getId()); ua.setAttempts(0); ua.setLastModified(new Date()); } } @Override public UserAttempts getUserAttempts(String username) { List<UserAttempts> userAttemptsList = new ArrayList<UserAttempts>(); userAttemptsList = sessionFactory.getCurrentSession().createQuery("from UserAttempts where username=?").setParameter(0, username).list(); if (userAttemptsList.size() > 0) return userAttemptsList.get(0); else return null; } }STEP 15 :- Create Custom UserDetailsService Class.
- Package: com.tutorialsdesk.service
- Filename: CustomUserDetailsService.java
package com.tutorialsdesk.service; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.tutorialsdesk.model.UserRole; @Service("customUserDetailsService") public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserService userService; @Transactional(readOnly=true) @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { com.tutorialsdesk.model.User user = userService.findUserByName(username); List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole()); return buildUserForAuthentication(user, authorities); } // Converts com.tutorialsdesk.model.User user to // org.springframework.security.core.userdetails.User private User buildUserForAuthentication(com.tutorialsdesk.model.User user, List<GrantedAuthority> authorities) { // boolean enabled = true; boolean accountNotExpired = true; boolean credentialsNotExpired = true; // boolean accountNotLocked = true; return new User(user.getUsername(), user.getPassword(), user.isEnabled(), accountNotExpired, credentialsNotExpired, user.isAccountNonLocked(), authorities); } private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) { Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>(); // Build user's authorities for (UserRole userRole : userRoles) { setAuths.add(new SimpleGrantedAuthority(userRole.getRole())); } List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths); return Result; } }STEP 16 :- Create Custom User Authentication Handler Class.
- Package: com.tutorialsdesk.handler
- Filename: LimitLoginAuthenticationProvider.java
package com.tutorialsdesk.handler; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import com.tutorialsdesk.model.UserAttempts; import com.tutorialsdesk.service.UserService; @Component("authenticationProvider") public class LimitLoginAuthenticationProvider extends DaoAuthenticationProvider { @Autowired private UserService userService; @Autowired @Qualifier("customUserDetailsService") @Override public void setUserDetailsService(UserDetailsService userDetailsService) { super.setUserDetailsService(userDetailsService); } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { try { Authentication auth = super.authenticate(authentication); //if reach here, means login success, else an exception will be thrown //reset the user_attempts userService.resetFailAttempts(authentication.getName()); return auth; } catch (BadCredentialsException e) { //invalid login, update to user_attempts userService.updateFailAttempts(authentication.getName()); throw e; } catch (LockedException e){ //this user is locked! String error = ""; UserAttempts userAttempts = userService.getUserAttempts(authentication.getName()); if(userAttempts!=null){ Date lastAttempts = userAttempts.getLastModified(); error = "User account is locked! <br><br>Username : " + authentication.getName() + "<br>Last Attempts : " + lastAttempts; }else{ error = e.getMessage(); } throw new LockedException(error); } } }STEP 17 :- Create jsp files in /WebContent/WEB-INF/views folder
- Filename: login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@page session="true"%> <html> <head> <title>Login Page</title> <style> .error { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .msg { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } #login-box { width: 300px; padding: 20px; margin: 100px auto; background: #fff; -webkit-border-radius: 2px; -moz-border-radius: 2px; border: 1px solid #000; } </style> </head> <body onload='document.loginForm.username.focus();'> <h1>Spring Security Login Form (Limit Login Attempts)</h1> <div id="login-box"> <h2>Login with Username and Password</h2> <c:if test="${not empty error}"> <div class="error">${error}</div> </c:if> <c:if test="${not empty msg}"> <div class="msg">${msg}</div> </c:if> <form name='loginForm' action="<c:url value='/login' />" method='POST'> <table> <tr> <td>User:</td> <td><input type='text' name='username'></td> </tr> <tr> <td>Password:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="submit" /></td> </tr> </table> <input type="hidden" name="language" value="EN" /> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> </div> </body> </html>
- Filename: welcome.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>HelloWorld page</title> </head> <body> Greeting : ${greeting} This is a welcome page. <a href="<c:url value="/logout" />">Logout</a> <br/> <br/> <br/> <a href="<c:url value="/admin" />">Admin Page</a> ( Only Admin user can access this ) <br/> <br/> <a href="<c:url value="/api" />">API Page</a> ( Admin or API user can access this ) </body> </html>
- Filename: admin.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>HelloWorld Admin page</title> </head> <body> Dear <strong>${user}</strong>, Welcome to Admin Page. <a href="<c:url value="/home" />">Home </a> | <a href="<c:url value="/logout" />"> Logout</a> </body> </html>
- Filename: api.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>DBA page</title> </head> <body> Dear <strong>${user}</strong>, Welcome to API Page. <a href="<c:url value="/home" />">Home </a> | <a href="<c:url value="/logout" />"> Logout</a> </body> </html>
- Filename: accessDenied.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <title>AccessDenied page</title> <style> .error { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #a94442; background-color: #f2dede; border-color: #ebccd1; } </style> </head> <body> Dear <strong>${user}</strong>, <br/> <br/> <div class="error">You are not authorized to access this page.</div> <br/> <br/> <a href="<c:url value="/home" />">Home </a> | <a href="<c:url value="/logout" />"> Logout</a> </body> </html>STEP 18 :- Run your project enter below URL in your browser
http://localhost:8080/SpringSecurityLimitLoginAttemptJavaConfig/
Keep visiting TutorialsDesk for more tutorials and practical programming examples on Spring MVC. Hope we are able to explain you Spring MVC security limit login attempts example using Java configuration Example, if you have any questions or suggestions please write to us using contact us form.
Please share us on social media if you like the tutorial.
Blogger Comment
Facebook Comment