Creating a Web Application With Spring 4 MVC Example for User Signup, Login and Logout with Password encoder Tutorial

Overview

In this tutorial, we show you how to create Web Application with Spring 4 MVC, Spring Security User Registration, Spring MVC Login Form and Logout Example using Eclipse IDE, Mysql Database

Follow the steps mentioned below to develop this application.

Spring 4 MVC Example for User Signup, Login and Logout with Password encoder


Video Tutorials

Create Database

CREATE DATABASE `jack_rutorial_demo`;

Create Database Table

Creating `users` Table
CREATE TABLE  `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL DEFAULT '',
  `password` varchar(200) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Creating `user_roles` Table
CREATE TABLE  `user_roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL DEFAULT '',
  `role` varchar(45) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Creating `persistent_logins` Table
CREATE TABLE  `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Creating a default admin user

The following code creates a users named “admin” with password is '123', defines an “ROLE_ADMIN” role.
INSERT INTO USERS(USERNAME,PASSWORD) VALUES('admin','$2a$10$Ii8O.wtxIeYQuXcbhcQ/WOngxwb1KrnAVOOLi6SaW8KfPWq7O6tsa');
INSERT INTO USER_ROLES(USERNAME,ROLE) VALUES('admin','ROLE_ADMIN');

Project Structure 

Project Structure Spring 4 MVC Signup Login Logout Form with password encoder

Create Maven Project

  • Launch Eclipse IDE.
  • Go to File-> New-> Others... Select Maven Project under Maven category then click Next.
  • In New Maven Project wizard, select "Create a simpel project(skip archetype selection)" and click on Next
  • In next wizard, type "com.jackrutorial" in the "Group ID:" field
  • Type "SpringMVCSignupLoginPasswordEncoder" in the "Artifact Id:" field
  • Packaging -> War
  • Click Finish.

Update pom.xml to include required dependencies

Open pom.xml file and add the following dependencies in it.
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.jackrutorial</groupId>
 <artifactId>SpringMVCSignupLoginPasswordEncoder</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>

 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>4.3.0.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.3.0.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>4.0.4.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>4.0.4.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jdbc</artifactId>
   <version>4.3.0.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>jstl</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
  </dependency>

  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.0</version>
   <scope>provided</scope>
  </dependency>

 </dependencies>

 <build>
  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.4</version>
     <configuration>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
 </build>

</project>

Configure WebApp and Spring Security

  • Right click to the src folder, select New -> Package
  • Enter "com.jackrutorial.config" in Name: field
  • Click Finish
Create a WebConfig class under com.jackrutorial.config package and write the following code in it
package com.jackrutorial.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.jackrutorial" })
public class WebConfig extends WebMvcConfigurerAdapter {
 
 @Autowired
 DataSource dataSource;
 
 @Bean
 public NamedParameterJdbcTemplate geNamedParameterJdbcTemplate(){
  return new NamedParameterJdbcTemplate(dataSource);
 }
 
 @Bean
 public DataSource getDataSource(){
  DriverManagerDataSource ds = new DriverManagerDataSource();
  ds.setDriverClassName("com.mysql.jdbc.Driver");
  ds.setUrl("jdbc:mysql://localhost/jack_rutorial_demo");
  ds.setUsername("root");
  ds.setPassword("root");
  
  return ds;
 }
 
 @Bean
 public InternalResourceViewResolver viewResolver(){
  InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  viewResolver.setViewClass(JstlView.class);
  viewResolver.setPrefix("/WEB-INF/jsp/");
  viewResolver.setSuffix(".jsp");
  
  return viewResolver;
 }
 
 @Bean
 public ResourceBundleMessageSource messageSource(){
  ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
  rb.setBasenames(new String[]{"validation"});
  
  return rb;
 }
}

Create a WebInitializer class under com.jackrutorial.config package and write the following code in it
package com.jackrutorial.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer  {

 @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { WebConfig.class};
    }
  
    @Override
    protected Class[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}
Create a SercurityConfig class under com.jackrutorial.config package and write the following code in it
package com.jackrutorial.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import com.jackrutorial.service.LoginServiceImpl;


@Configuration
@EnableWebSecurity
public class SercurityConfig extends WebSecurityConfigurerAdapter {
 
 @Autowired
 DataSource dataSource;
 
 @Autowired
 LoginServiceImpl loginServiceImpl;
 
 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(loginServiceImpl);
  auth.authenticationProvider(authenticationProvider());
 }
 
 @Bean
 public DaoAuthenticationProvider authenticationProvider(){
  DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
  authenticationProvider.setUserDetailsService(loginServiceImpl);
  authenticationProvider.setPasswordEncoder(passwordEncoder());
  
  return authenticationProvider;
 }
 
 @Bean
 public PasswordEncoder passwordEncoder(){
  return new BCryptPasswordEncoder();
 }
 
 @Override
 protected void configure(HttpSecurity http) throws Exception{
  http.csrf().disable();
  
  http.authorizeRequests().antMatchers("/login", "/user/sigup", "/user/register").permitAll();
  http.authorizeRequests().antMatchers("/", "/home")
.access("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')");
  http.authorizeRequests().antMatchers("/user/list")
.access("hasRole('ROLE_ADMIN')");
  
  http.authorizeRequests().and().formLogin()
   .loginProcessingUrl("/j_spring_security_check")
   .loginPage("/login")
   .failureUrl("/login?error=true")
   .usernameParameter("username")
   .passwordParameter("password")
   .and().logout().logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/login")
   .and().rememberMe()
   .tokenRepository(persistentTokenRepository())
   .tokenValiditySeconds(60*60)
   .and().exceptionHandling().accessDeniedPage("/accessDenied");
 }
 
 @Bean
 public PersistentTokenRepository persistentTokenRepository(){
  JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
  db.setDataSource(dataSource);
  
  return db;
 }
 
}

Create a SecurityInitializer class under com.jackrutorial.config package and write the following code in it
package com.jackrutorial.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

Creating Model Layer

Create a UserInfo class under package com.jackrutorial.model and write the following code in it 
package com.jackrutorial.model;

public class UserInfo {
 private String username;
 private String password;
 
 public UserInfo() {
  super();
 }
 public UserInfo(String username, String password) {
  super();
  this.username = username;
  this.password = password;
 }
 
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
}

Creating Form Layer

Create a UserForm class under package com.jackrutorial.form and write the following code in it
package com.jackrutorial.form;

public class UserForm {
 private String username;
 private String password;
 private String confirmPassword;
 
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public String getConfirmPassword() {
  return confirmPassword;
 }
 public void setConfirmPassword(String confirmPassword) {
  this.confirmPassword = confirmPassword;
 }
}

Creating DAO Layer

Create a LoginDao Interface under com.jackrutorial.dao package and write the following code in it

package com.jackrutorial.dao;

import java.util.List;

import com.jackrutorial.model.UserInfo;

public interface LoginDao {

 UserInfo findUserInfo(String username);
 
 List getUserRoles(String username);
}
Create a LoginDaoImpl class implements LoginDao Interface under com.jackrutorial.dao package and write the following code in it
package com.jackrutorial.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;

import com.jackrutorial.model.UserInfo;

@Repository
public class LoginDaoImpl implements LoginDao {
 
 NamedParameterJdbcTemplate namedParameterJdbcTemplate;
 
 @Autowired
 public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
  this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
 }

 public UserInfo findUserInfo(String username) {
  String sql = "select username,password from users where username = :username";
  
  UserInfo userInfo = namedParameterJdbcTemplate
.queryForObject(sql, getSqlParameterSource(username, ""), new UserInfoMapper());
  
  return userInfo;
 }
 
 private static final class UserInfoMapper implements RowMapper{

  public UserInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
   String username = rs.getString("username");
   String password = rs.getString("password");
   return new UserInfo(username, password);
  }
  
 }
 
 private SqlParameterSource getSqlParameterSource(String username, String password){
  MapSqlParameterSource parameterSource = new MapSqlParameterSource();
  parameterSource.addValue("username", username);
  parameterSource.addValue("password", password);
  
  return parameterSource;
 }

 public List getUserRoles(String username) {
  String sql = "select role from user_roles where username = :username";
  
  List roles = namedParameterJdbcTemplate
.queryForList(sql, getSqlParameterSource(username, ""), String.class);
  
  return roles;
 }

}
Create a UserDao interface under com.jackrutorial.dao package and write the following code in it
package com.jackrutorial.dao;

import java.util.List;

import com.jackrutorial.model.UserInfo;

public interface UserDao {
 
 public List list();
 
 public UserInfo findUserByUsername(String username);
 
 public void update(String username, String password);
 
 public void add(String username, String password);
 
 public boolean userExists(String username);
 
}
Create a UserDaoImpl class implements UserDao Interface under com.jackrutorial.dao package and write the following code in it 
package com.jackrutorial.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;

import com.jackrutorial.model.UserInfo;

@Repository
public class UserDaoImpl implements UserDao {
 
 NamedParameterJdbcTemplate namedParameterJdbcTemplate;
 
 @Autowired
 public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
  this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
 }

 public List list() {
  String sql = "select username from users";
  
  List list = namedParameterJdbcTemplate
.query(sql, getSqlParameterSource(null, null), new UserMapper());
  
  return list;
 }
 
 private SqlParameterSource getSqlParameterSource(String username, String password){
  MapSqlParameterSource parameterSource = new MapSqlParameterSource();
  if(username != null){
   parameterSource.addValue("username", username);
  }
  if(password != null){
   parameterSource.addValue("password", password);
  }
  
  return parameterSource;
 }
 
 private static final class UserMapper implements RowMapper{

  public UserInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
   UserInfo user = new UserInfo();
   user.setUsername(rs.getString("username"));
   
   return user;
  }
  
 }

 public UserInfo findUserByUsername(String username) {
  String sql = "select username from users where username = :username";
  
  List list = namedParameterJdbcTemplate
.query(sql, getSqlParameterSource(username, null), new UserMapper());
  
  return list.get(0);
 }

 public void update(String username, String password) {
  String sql = "update users set password = :password where username = :username";
  
  namedParameterJdbcTemplate.update(sql, getSqlParameterSource(username, password));
  
 }

 public void add(String username, String password) {
  String sql = "insert into users(username, password) values(:username, :password)";
  namedParameterJdbcTemplate.update(sql, getSqlParameterSource(username, password));
  
  sql = "insert into user_roles(username, role) values(:username, 'ROLE_USER')";
  namedParameterJdbcTemplate.update(sql, getSqlParameterSource(username, password));
 }

 public boolean userExists(String username) {
  String sql = "select * from users where username = :username";
  
  List list = namedParameterJdbcTemplate
.query(sql, getSqlParameterSource(username, null), new UserMapper());
  
  if(list.size() > 0){
   return true;
  }
  
  return false;
 }

}

Creating Service Layer

Create a LoginServiceImpl class implements UserDetailsService Interface under com.jackrutorial.service package and write the following code in it 
package com.jackrutorial.service;

import java.util.ArrayList;
import java.util.List;

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 com.jackrutorial.dao.LoginDao;
import com.jackrutorial.model.UserInfo;

@Service
public class LoginServiceImpl implements UserDetailsService {
 
 LoginDao loginDao;
 
 @Autowired
 public void setLoginDao(LoginDao loginDao) {
  this.loginDao = loginDao;
 }

 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  UserInfo userInfo = loginDao.findUserInfo(username);
  
  if(userInfo == null){
   throw new UsernameNotFoundException("username was not found in the database");
  }
  
  List roles = loginDao.getUserRoles(username);
  
  List grantList = new ArrayList();
  
  if(roles != null){
   for(String role : roles){
    GrantedAuthority authority = new SimpleGrantedAuthority(role);
    grantList.add(authority);
   }
  }
  
  UserDetails userDetails = new User(userInfo.getUsername(), userInfo.getPassword(), grantList);
  
  return userDetails;
 }

}
Create a UserService Interface under package com.jackrutorial.service package and write the following code in it 
package com.jackrutorial.service;

import java.util.List;

import com.jackrutorial.model.UserInfo;

public interface UserService {
 
 public List list();
 
 public UserInfo findUserByUsername(String username);
 
 public void update(String username, String password);
 
 public void add(String username, String password);
 
 public boolean userExists(String username);
}

Create a UserServiceImpl class implements UserService Interface under com.jackrutorial.service package and write the following code in it 
package com.jackrutorial.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.jackrutorial.dao.UserDao;
import com.jackrutorial.model.UserInfo;

@Service
public class UserServiceImpl implements UserService {
 
 UserDao userDao;
 
 @Autowired
 private PasswordEncoder passwordEncoder;
 
 @Autowired
 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }

 public List list() {
  return userDao.list();
 }

 public UserInfo findUserByUsername(String username) {
  return userDao.findUserByUsername(username);
 }

 public void update(String username, String password) {
  userDao.update(username, passwordEncoder.encode(password));
 }

 public void add(String username, String password) {
  userDao.add(username, passwordEncoder.encode(password));
 }

 public boolean userExists(String username) {
  return userDao.userExists(username);
 }

}

Custom Validator

Create a SignupValidator class implements Validator Interface under com.jackrutorial.validator package and write the following code in it 
package com.jackrutorial.validator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.jackrutorial.form.UserForm;
import com.jackrutorial.service.UserService;

@Component
public class SignupValidator implements Validator {
 
 @Autowired
 UserService userService;

 public boolean supports(Class clazz) {
  return UserForm.class.isAssignableFrom(clazz);
 }

 public void validate(Object target, Errors errors) {
  UserForm user = (UserForm) target;
  
  ValidationUtils.rejectIfEmpty(errors, "username", "notEmpty.username");
  ValidationUtils.rejectIfEmpty(errors, "password", "notEmpty.password");
  ValidationUtils.rejectIfEmpty(errors, "confirmPassword", "notEmpty.confirmPassword");
  
  if(user.getPassword() != null && user.getConfirmPassword() != null && 
!user.getPassword().equals(user.getConfirmPassword())){
   errors.rejectValue("password", "notMatch.confirmPassword");
  }
  
  if(userService.userExists(user.getUsername())){
   errors.rejectValue("username", "exists.username");
  }
 }

}
We will define the error codes and their corresponding values in validation.properties file under src/main/resources folder as follows. 
notEmpty.username=Username is required
notEmpty.password=Password is required
notEmpty.confirmPassword=Confirm Password is required
notMatch.confirmPassword=Password does not match the confirm password
exists.username=username already exists

Creating Controller Layer

Create a LoginController class under package com.jackrutorial.controller package and write the following code in it 
package com.jackrutorial.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value="/")
public class LoginController {

 @RequestMapping(value="/login", method=RequestMethod.GET)
 public ModelAndView login(@RequestParam(value="error", required = false) String error){
  ModelAndView model = new ModelAndView();
  
  if(error != null){
   model.addObject("msg", "The username or password is incorrect!");
  }
  
  model.setViewName("login/login");
  
  return model;
 }
 
 @RequestMapping(value={"/", "/home"}, method=RequestMethod.GET)
 public ModelAndView home(){
  ModelAndView model = new ModelAndView();
  model.setViewName("home/home");
  
  return model;
 }
 
 @RequestMapping(value="/logout", method=RequestMethod.GET)
 public String logoutPage(HttpServletRequest request, HttpServletResponse response){
  Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  
  if(auth != null){
   new SecurityContextLogoutHandler().logout(request, response, auth);
  }
  
  return "redirect:/login";
 }
 
 @RequestMapping(value="/accessDenied", method=RequestMethod.GET)
 public ModelAndView accessDenied(){
  ModelAndView model = new ModelAndView();
  model.setViewName("errors/access_denied");
  return model;
 }
}
Create a UserController class under package com.jackrutorial.controller package and add the custom validator in it. 
package com.jackrutorial.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.jackrutorial.form.UserForm;
import com.jackrutorial.model.UserInfo;
import com.jackrutorial.service.UserService;
import com.jackrutorial.validator.SignupValidator;

@Controller
@RequestMapping("/user")
public class UserController {
 
 @Autowired
 SignupValidator signupValidator;

 @Autowired
 UserService userService;
 
 @RequestMapping(value="/list", method=RequestMethod.GET)
 public ModelAndView list(){
  ModelAndView model = new ModelAndView("user/list");
  model.addObject("list", userService.list());
  
  return model;
 }
 
 @RequestMapping(value="/changePass/{username}", method=RequestMethod.GET)
 public ModelAndView changePass(@PathVariable("username") String username){
  ModelAndView model = new ModelAndView("user/change_pass");
  model.addObject("user", userService.findUserByUsername(username));
  
  return model;
 }
 
 @RequestMapping(value="/save", method=RequestMethod.POST)
 public ModelAndView save(@ModelAttribute("user") UserInfo user){
  ModelAndView model = changePass(user.getUsername());
  userService.update(user.getUsername(), user.getPassword());
  model.addObject("msg", "Your password has been changed successfully!");
  
  return model;
 }
 
 @RequestMapping(value="/signup", method=RequestMethod.GET)
 public ModelAndView signup(){
  ModelAndView model = new ModelAndView("user/signup");
  model.addObject("userForm", new UserForm());
  
  return model;
 }
 
 @RequestMapping(value="/register", method=RequestMethod.POST)
 public String register(@ModelAttribute("userForm") UserForm userForm, 
BindingResult result, RedirectAttributes redirectAttributes){
  
  signupValidator.validate(userForm, result);
  
  if(result.hasErrors()){
   return "/user/signup";
  } else {
   userService.add(userForm.getUsername(), userForm.getPassword());
   redirectAttributes.addFlashAttribute("msg", "Your account has been created successfully!");
   
   return "redirect:/login";
  }
 }
 
}

Creating JSP Views

Create login folder under src\main\webapp\WEB-INF\jsp folder.
Create login.jsp file under src\main\webapp\WEB-INF\jsp\login folder and write the following code in it.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login</title>
</head>
<body>
 <form name="loginForm" action='<c:url value="j_spring_security_check" />' method="post" >
  <table>
   <tr>
    <td colspan="2">Login</td>
   </tr>
   <tr>
    <td colspan="2">${msg }</td>
   </tr>
   <tr>
    <td>Username: </td>
    <td>
     <input type="text" name="username" />
    </td>
   </tr>
   <tr>
    <td>Password: </td>
    <td>
     <input type="password" name="password" />
    </td>
   </tr>
   <tr>
    <td>Remember Me: </td>
    <td>
     <input type="checkbox" name="remember-me" />
    </td>
   </tr>
   <tr>
    <td></td>
    <td>
     <button type="submit">Login</button>
    </td>
   </tr>
   <tr>
    <td></td>
    <td>
     <a href='<c:url value="/user/signup" />'>Sign up</a>
    </td>
   </tr>
  </table>
 </form>
</body>
</html>
Create home folder under src\main\webapp\WEB-INF\jsp folder.
Create home.jsp file under src\main\webapp\WEB-INF\jsp\home folder and write the following code in it.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home</title>
</head>
<body>
 <a href='<c:url value="/logout" />'>Logout</a>
 <h1>Welcome 
 <c:if test="${pageContext.request.userPrincipal.name != null }">
 ${pageContext.request.userPrincipal.name }
 </c:if> </h1>
 <br/>
 <a href='<c:url value="/user/list" />'>Users List</a>
</body>
</html>

Create user folder under src\main\webapp\WEB-INF\jsp folder.
Create signup.jsp file under src\main\webapp\WEB-INF\jsp\user folder and write the following code in it.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Signup</title>
</head>
<body>
 <spring:url value="/user/register" var="registerURL" />
 <form:form action="${registerURL}" modelAttribute="userForm" method="post" >
  <label>Username: </label>
  <form:input path="username" type="text" />
  <form:errors path="username" />
  <br/>
  <label>Password: </label>
  <form:password path="password" />
  <form:errors path="password" />
  <br/>
  <label>Confirm Password: </label>
  <form:password path="confirmPassword" />
  <form:errors path="confirmPassword" />
  <br/>
  <button type="submit">Sign up</button>
  
 </form:form>
 
</body>
</html>
Create list.jsp file under src\main\webapp\WEB-INF\jsp\user folder and write the following code in it.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Users List</title>
</head>
<body>
 <a href='<c:url value="/logout" />'>Logout</a>
 <br/>
 <table border="1">
  <tr>
   <td>Username</td>
   <td>Action</td>
  </tr>
  <c:forEach items="${list }" var="user">
   <tr>
    <td>${user.username }</td>
    <td>
     <spring:url value="/user/changePass" var="changePassURL" />
     <a href="${changePassURL }/${user.username }">Change Pass</a> 
    </td>
   </tr>
  </c:forEach>
 </table>
 
</body>
</html>
Create change_pass.jsp file under src\main\webapp\WEB-INF\jsp\user folder and write the following code in it.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Change Password</title>
</head>
<body>
 <spring:url value="/user/save" var="saveURL" />
 <form:form method="post" modelAttribute="user" action="${saveURL }">
  <form:hidden path="username"/>
  <table border="1">
   <tr>
    <td colspan="2">${msg }</td>
   </tr>
   <tr>
    <td>Username: </td>
    <td>${user.username }</td>
   </tr>
   <tr>
    <td>Password: </td>
    <td><form:password path="password" /></td>
   </tr>
   <tr>
    <td></td>
    <td>
     <button type="submit" >Change Password</button>
    </td>
   </tr>
  </table>
 </form:form>
 
</body>
</html>
Create errors folder under src\main\webapp\WEB-INF\jsp folder.
Create access_denied.jsp file under src\main\webapp\WEB-INF\jsp\errors folder and write the following code in it.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access denied</title>
</head>
<body>
 <h1>Access denied!</h1>
</body>
</html>

Building

  • Right click this project
  • Select Run As -> Maven clean
  • Right click this project
  • Select Run As -> Maven install

Configuring Apache Tomcat

  • Under Servers tab, click link "No servers are available. Click this link to create a new server ...", select Apache tomcat 7
  • Click Finish

  • Right click "Tomcat v7.0 Server at localhost [Stopped, Republish]", select "Add and Remove ..."
  • Add SpringMVCSignupLoginPasswordEncoder project, then Click Finish
  • Open server.xml file under Servers Folder
  • Find line
<Context docBase="SpringMVCSignupLoginPasswordEncoder" path="/SpringMVCSignupLoginPasswordEncoder" reloadable="true" source="org.eclipse.jst.jee.server:SpringMVCSignupLoginPasswordEncoder" />

Update its as below:

<Context docBase="<Project Folder Location>\SpringMVCSignupLoginPasswordEncoder\target\SpringMVCSignupLoginPasswordEncoder-0.0.1-SNAPSHOT\" path="/SpringMVCSignupLoginPasswordEncoder" reloadable="true" />

  • Copy mysql-connector-java-5.1.45-bin.jar file to <Apache Tomcat Folder Location>\apache-tomcat-7.0.68\lib\

Watch video add Apache Tomcat Server in Eclipse IDE


Run application & Check result

  • Start Apache Tomcat from Eclipse IDE.
  • Type the following URLs in browser's address bar to open the login from.
http://localhost:8080/SpringMVCSignupLoginPasswordEncoder/
spring mvc login form

Enter username/password: admin/123 to login
welcome admin home page

user list page

change password page
signup page form

Required Libraries

Previous Post
Next Post

post written by: