Spring Security Custom Login with JPA Hibernate Example

In this tutorial, let us see that how to configure and  create a custom login page  using spring security with JPA Hibernate   in easy steps  with the help of Maven in Eclipse.  In this example, we will create a Custom Authentication Filter which extends UsernamePasswordAuthenticationFilter that will override attemptAuthentication and obtainUsername  for accepting extra parameter from the login page.  There are other ways  to  pass an additional parameter with the spring security login page which we can discuss in different post.
The default spring authentication accepts only user name and password from the login page.  username-parameter=”username” password-parameter=”password”
There may be requirement to use combination of one or more fields as user id for eg. (username + Group name).  In this example,  user id will be combination of email and mobile number i.e You can use this program to login using email and mobile number together
You can also  use this program to login using email  or  mobile number  by doing small change in the code.
Some of highlights covered in this tutorial are
1. Passing extra parameter through login page and implementing Custom Authentication filter
2. Using custom query for finding user name
3. Role based menus
4. Customized user details.
Now let us see the technical part.  The Technology used in this example
1. Spring 4.2.0
2. Spring Security 4.1.0
3. Spring Data JPA – 1.8.2
4. Hibernate 4.3.11
5. MySQL 5.1.36
6. JPA 1.8.2
7. Java 1.8
8. Maven
9. Eclipse with Apache server
Project Structure
 
Step 1: Create a project  (springhibernatelogin) with maven support
Step 2:  Add Spring Dependencies for the project using maven i.e add necessary lines in the pom.xml  to load necessary jars from mavan repository
pom.xml
<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>javaonline</groupId>
  <artifactId>spinghibernatelogin</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>SpringHibernateLogin</name>
<properties>
		<spring.version>4.2.0.RELEASE</spring.version>
		<spring-security.version>4.1.0.RELEASE</spring-security.version>
		<spring-data-jpa.version>1.8.2.RELEASE</spring-data-jpa.version>
		<hibernate.version>4.3.11.Final</hibernate.version>
		<hibernate-validator.version>5.2.1.Final</hibernate-validator.version>
		<mysql-connector.version>5.1.36</mysql-connector.version>
		<commons-dbcp.version>1.4</commons-dbcp.version>
		<jstl.version>1.2</jstl.version>
		<junit.version>4.12</junit.version>
		<logback.version>1.1.3</logback.version>
		<failOnMissingWebXml>false</failOnMissingWebXml>
	</properties>


	

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring-security.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring-security.version}</version>
		</dependency>


		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<version>1.2</version>
		</dependency>


		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>${hibernate-validator.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>${spring-data-jpa.version}</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		
		
			<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>${commons-dbcp.version}</version>
		</dependency>
		

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector.version}</version>
		</dependency>

	

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>

	

		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
		</dependency>

		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-taglibs</artifactId>
		    <version>4.2.0.RELEASE</version>
		</dependency>
	
	
			<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.5.0</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.eclipse.jetty</groupId>
				<artifactId>jetty-maven-plugin</artifactId>
				<version>9.2.11.v20150529</version>
				<configuration>
					<scanIntervalSeconds>10</scanIntervalSeconds>
					<webApp>
						<contextPath>/</contextPath>
					</webApp>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Step 3:  Now Let us create  necessary java files and jsp

 i) Let us create login jsp file which contains the following fields   User name will be the combination of email id and mobile number
        email as userid
        mobile number (extra parameter)
        password
 login.jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<c:set var="contextPath" value="${pageContext.request.contextPath}"/>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Log in</title>
    <link href="${contextPath}/resources/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>

<div class="container">

    <form method="POST" action="${contextPath}/login" class="form-signin">
        <h2 class="form-heading">Log in</h2>

            <span>${message}</span>
            <input name="username" type="text" class="form-control" placeholder="Email"  autofocus="true"/>
            <input name="extraparam" type="text" class="form-control" placeholder="Mobile Number"/>
            <input name="password" type="password" class="form-control" placeholder="Password"/>
            <span>${error}</span>
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

            <button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>

    </form>

</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>
</body>
</html>

ii) Create menu.jsp  to display menus based on the role of a user

menu.jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>


<sec:authentication var="user" property="principal" />
<c:set var="contextPath" value="${pageContext.request.contextPath}" />

		<c:if test="${pageContext.request.userPrincipal.name != null}">
			<form id="logoutForm" method="POST" action="${contextPath}/logout">
				<input type="hidden" name="${_csrf.parameterName}"
					value="${_csrf.token}" />
			</form>

			<h4>
				[${user.message}] ${pageContext.request.userPrincipal.name} 
						<sec:authorize access="hasAnyRole('ROLE_USER')">
								[${user.username}]
						</sec:authorize>
				</h4>				
						
   			   <a onclick="document.forms['logoutForm'].submit()">Logout</a>
		

		</c:if>

	</br>
</br>
<sec:authorize access="hasAnyRole('ROLE_USER','ROLE_ADMIN', 'ROLE_SU')">

<c:forEach items="${menuList}" var="menu">
    <sec:authorize url="${menu.url}">
        <a href=${contextPath}${menu.url}>${menu.label}</a> </br>
    </sec:authorize>
</c:forEach>

</sec:authorize>

 

iii)  Create welcome.jsp to display contents after successful login
                This welcome page displays user name and menus based on the role.
welcome.jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec"
	uri="http://www.springframework.org/security/tags"%>

<c:set var="contextPath" value="${pageContext.request.contextPath}" />

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">

<meta name="author" content="">

<title>Welcome</title>

<link href="${contextPath}/resources/css/style.css" rel="stylesheet">

<link href="${contextPath}/resources/css/bootstrap.min.css"
	rel="stylesheet">
<link rel="stylesheet"
	href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">


<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>

</head>
<body>

	<sec:authentication var="user" property="principal" />

	<sec:authorize access="isAuthenticated()">

		<div class="container-fluid">

			<div class="row">

 			<div class="col-sm-2" ><jsp:include page="${request.contextPath}/loadMenuItem"></jsp:include></div>

				<div class="col-sm-10 myStyle" >
	
						<!-- Page contents goes here -->
	
				</div>
			</div>
		</div>

	</sec:authorize>
</body>


</html>

iv)  Create necessary java files for login model

 User.java
package javaonline.login.model;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "user")
public class User implements Serializable {
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Long id;
    private String email;
    private String mobile;
	private String password;
    private String message;
 	private String passwordConfirm;
    private String oldPassword;

   	private Set<Role> roles;

 
  	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
   	
    public String getEmail() {
  		return email;
  	}

  	public void setEmail(String email) {
  		this.email = email;
  	}
   	
    public String getMessage() {
 		return message;
 	}

 	public void setMessage(String message) {
 		this.message = message;
 	}
   
    @Transient
	public String getOldPassword() {
		return oldPassword;
	}

	public void setOldPassword(String oldPassword) {
		this.oldPassword = oldPassword;
	}



    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

   

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Transient
    public String getPasswordConfirm() {
        return passwordConfirm;
    }

    public void setPasswordConfirm(String passwordConfirm) {
        this.passwordConfirm = passwordConfirm;
    }

    
    @ManyToMany
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
    

}

Role.java

package javaonline.login.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import javaonline.menu.model.Menus;

@Entity
@Table(name = "role")
public class Role {
    private Long id;
    private String name;
    private Set<User> users;
    private Set<Menus> roleMenus; // for menus 


    @OneToMany(mappedBy = "role")
    @javax.persistence.OrderBy("menu_order")
	public Set<Menus> getRoleMenus() {
		return roleMenus;
	}

	
	 public void setRoleMenus(Set<Menus> roleMenus) {
		this.roleMenus = roleMenus;
	}

	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany(mappedBy = "roles")
    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }
    
}

MyUserDetails.java

                  To  make user details as customized one,  MyUserDetails class  has been created that extends  org.springframework.security.core.userdetails.User. In this example, additional parameter message (just to display on welcome page after successful login) is accepted along with user name and password.
package javaonline.login.model;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;

public class MyUserDetails extends org.springframework.security.core.userdetails.User {

	private String message;

public String getMessage() {
		return message;
	}


public void setMessage(String message) {
		this.message = message;
	}


public MyUserDetails(String username, String password,
        Collection<? extends GrantedAuthority> authorities, String message ) {
    super(username, password, authorities);
    
    this.message=message;
    // TODO Auto-generated constructor stub
}

}

v) Create login registry (UserRepository that extends JpaRepository) and create necessary methods for finding User details from the database. In this example, we have defined the following methods

  User findByEmail(String email)  – to find user name by Email
 User findByMobile(String mobile)- to find user name by Mobile number
 User findByEmailOrMobile(String email, String mobile) – to find user name by either Email or Mobile number
 @Query(“select p from User p where p.email = :email and p.mobile = :mobile”)
 User findByEmailAndMobile(@Param(“email”) String email, @Param(“mobile”) String mobile) – to find user name by the combination of both Email and Mobile number.     A custom is query is being used for the method findByEmailAndMobile 
UserRepository.java
package javaonline.login.repository;

import javaonline.login.model.User;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface UserRepository extends JpaRepository<User, Long> {
	
    User findByEmail(String email);
    
    User findByMobile(String mobile);
    
    User findByEmailOrMobile(String email, String mobile);
    
    @Query("select p from User p where p.email = :email and p.mobile = :mobile")
    User findByEmailAndMobile(@Param("email") String email,
                                 @Param("mobile") String mobile);
   
}

vi)   Create necessary java files for login service

CustomAuthenticationFilter.java

In this example, to accept extra parameter  from the login page,  we will create a Custom Authentication Filter which extends UsernamePasswordAuthenticationFilter.  Here the methods  attemptAuthentication and obtainUsername are overrided.

package javaonline.login.service;

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

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    protected String obtainUsername(HttpServletRequest request) {
        String username = super.obtainUsername(request);
        String extraparam = request.getParameter("extraparam");
        System.out.println("User name in authentication filter "+ username + " extra param "+ extraparam);
        return username+"|"+extraparam;
    }
    
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    	
    			 System.out.println("in attempt authentication");
    	         String username = obtainUsername(request);
    	         String password = obtainPassword(request);
    	 
    	         if (username == null) {
    	             username = "";
    	         }
    	 
    	         if (password == null) {
    	             password = "";
    	         }
    	 
    	         username = username.trim();
    	         
    	         System.out.println("user name in attempt auth " + username);
    	 
    	         UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
    
    	         setDetails(request, authRequest);
    	 
    	         return this.getAuthenticationManager().authenticate(authRequest);
    	     }

}

UserDetailsServiceImpl.java

         This class extends UserDetailService of Spring security  to  customize as per  our requirement. As the user name is combination of email and mobile number, we need to split by the delimiter (In this example |) to get email id and mobile number.

package javaonline.login.service;

import java.util.HashSet;
import java.util.Set;

import javaonline.login.model.MyUserDetails;
import javaonline.login.model.Role;
import javaonline.login.model.User;
import javaonline.login.repository.UserRepository;

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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

public class UserDetailsServiceImpl implements UserDetailsService{
    @Autowired
    private UserRepository userRepository;

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    	
    	System.out.println("in userdetail service");
    	
    
    	String[] parts = username.split("\\|");
    	String email = parts[0]; 
    	String mobile = parts[1];
    	
    	
        User user = userRepository.findByEmailAndMobile(email, mobile);
        
    	System.out.println("in userdetail service user "+ user.getEmail() +  "  mb " + user.getMobile() + " uder id "+ user.getId());

        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
       
        for (Role role : user.getRoles()){
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        System.out.println("pass = " + user.getPassword());
        
        MyUserDetails myUserDetails = new MyUserDetails (user.getEmail(), user.getPassword(), grantedAuthorities,user.getMessage());
        return myUserDetails;
    
        
     //   return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
    }
    
     
}

 

UserService.java

This interface is used to declare new methods related to User service. In this example two new methods are declared.

void save(User user);
String findLoggedInUsername();

package javaonline.login.service;

import javaonline.login.model.User;

public interface UserService {
    void save(User user);
    String findLoggedInUsername();
}

 

UserServiceImpl.java

This class implements the methods of the interface UserService

package javaonline.login.service;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javaonline.login.model.User;

@Service
public class UserServiceImpl implements UserService {
	
	@Override
	public void save(User user) {
	
		//write code to create user
		
	}

	
	    @Override
	    public String findLoggedInUsername() {
	        Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
	        if (userDetails instanceof UserDetails) {
	            return ((UserDetails)userDetails).getUsername();
	        }

	        return null;
	    }


}

 

vii)   Create necessary java files for menu model & menu service

Menu Model:
menus.java
                This is an entity class that represents menus table. It is used to retrieve menus  based on the user role.
package javaonline.menu.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javaonline.login.model.Role;

@Entity
@Table(name = "menus")
public class Menus {

	private Long menu_id;
	private String menu_name;
	private String menu_url;
	private short menu_order;

	private Role role;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Long getMenu_id() {
		return menu_id;
	}

	public void setMenu_id(Long menu_id) {
		this.menu_id = menu_id;
	}

	@ManyToOne
	@JoinColumn(name = "id")
	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public short getMenu_order() {
		return menu_order;
	}

	public void setMenu_order(short menu_order) {
		this.menu_order = menu_order;
	}

	public String getMenu_name() {
		return menu_name;
	}

	public void setMenu_name(String menu_name) {
		this.menu_name = menu_name;
	}

	public String getMenu_url() {
		return menu_url;
	}

	public void setMenu_url(String menu_url) {
		this.menu_url = menu_url;
	}

}

 

menu.java

This is a POJO class to hold menu name, menu url, etc..

package javaonline.menu.model;
public class Menu {
	
	private String id="";
	private String label="";
	private String url="";
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	
}

Menu Service:
RoleMenuService.java
package javaonline.menu.service;

import java.util.LinkedHashMap;

public interface RoleMenuService {

	public  LinkedHashMap<String, String> menuMap(String roleName);
		

}

RoleMenuServiceImpl.java

package javaonline.menu.service;

import java.util.LinkedHashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class RoleMenuServiceImpl implements RoleMenuService {

	@Autowired
	private RoleMenuDAO roleMenuDao;

	
	@Transactional(readOnly = true)
	public  LinkedHashMap<String, String> menuMap(String roleName) {
		System.out.println(" in find " + roleName);
	return	 roleMenuDao.menuMap(roleName);

	}


}

RoleMenuDAO.java

package javaonline.menu.service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import javaonline.login.model.Role;
import javaonline.menu.model.Menus;


@Component
@ComponentScan("javaonline.menu.service.*")
public class RoleMenuDAO {
	

	@PersistenceContext
	private EntityManager em;

	

	public List<Menus> findAll() {
		return em.createQuery("SELECT r FROM Menus r ").getResultList();
	}
	
	

	

	public Set<Menus> findMenus(String roleName) {
		Role m= (Role) em.createQuery( "SELECT c FROM role c WHERE c.name = :roleName ")
			    .setParameter("roleName", roleName).getSingleResult();
			
		return  m.getRoleMenus();
	}


	
	
public LinkedHashMap<String, String> menuMap(String roleName) {
		
		Role ro= (Role) em.createQuery( "SELECT c FROM Role c WHERE c.name = :roleName ")
			    .setParameter("roleName", roleName.trim()).getSingleResult();
		
		System.out.println("RO " + ro.getUsers().size());
		System.out.println("RO " + ro.getRoleMenus().size());
		System.out.println("RO " + ro.getId());
		System.out.println("RO " + ro.getName());
		
		
		LinkedHashMap<String,String> menuMapTmp=new LinkedHashMap<String,String>();
 		for ( Menus menu: ro.getRoleMenus())
		{
		System.out.println(" menus in role "+ menu.getMenu_name());
		menuMapTmp.put( menu.getMenu_name(),menu.getMenu_url());
		
		}
		return menuMapTmp;
		
	}

}

 

viii)  Create UserController for loading Welcome page and menus.
 UserController.java
package javaonline.login.web;

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

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javaonline.menu.model.Menu;
import javaonline.menu.service.RoleMenuService;

@Controller
@RequestMapping("/")
public class UserController {
  
	    @Autowired
	    RoleMenuService roleMenuService;


    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(Model model, String error, String logout) {
        if (error != null)
            model.addAttribute("error", "Your username and password is invalid.");

        if (logout != null)
            model.addAttribute("message", "You have been logged out successfully.");

        return "login";
    }
    
    
 

    @RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
    public String welcome(Model model) {
        return "welcome";
    } 
    
    
   
    @RequestMapping(value = "/loadMenuItem", method =  {RequestMethod.POST, RequestMethod.GET})
    public String loadMenu(HttpServletRequest request, Model model, Authentication authentication) {
    	
  	List<Menu> menuList=new ArrayList<Menu>();
    	
    	System.out.println("menu map " +roleMenuService.menuMap("ROLE_USER"));
    	
    	System.out.println("role name "+authentication.getAuthorities() );
    	
    	
    	int[] i = { 0 };
    	
    	Iterator it=authentication.getAuthorities().iterator();
    	
    	while (it.hasNext())
    	{
    	
        roleMenuService.menuMap(it.next().toString()).forEach((k,v)->
        {
        	
        	Menu m1=new Menu();
        	m1.setId(i[0]+++"");
        	m1.setLabel(k);
        	m1.setUrl(v);
        	menuList.add(m1);
        	
        }
        		);
    	}
    	
    	
    	model.addAttribute("menuList",menuList);
    	
          return "menu/menu";
    }
    
}

 

 Step 4:  Create web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <display-name>Spring Loin Example</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/appcontext-root.xml</param-value>
    </context-param>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
              <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

    <session-config>
  <session-timeout>15</session-timeout>
</session-config>

    <error-page>
<error-code>500</error-code>
<location>/login</location>
</error-page>

<error-page>
<error-code>404</error-code>
<location>/login</location>
</error-page>
    
</web-app>

 

Step 5:  Create Application Properties for configuring data source
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springtest?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=<your mysql database server password>

Step 6.  Create necessary Config files

appcontext_root.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="appcontext-mvc.xml"/>

    <import resource="appcontext-data.xml"/>

    <import resource="appcontext-security.xml"/>

    <context:component-scan base-package="javaonline.login.*"/>
  
    <context:property-placeholder location="classpath:application.properties"/>

</beans>

appcontext-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security
		http://www.springframework.org/schema/security/spring-security.xsd">


	<global-method-security secured-annotations="enabled"
		pre-post-annotations="enabled" />

	<http auto-config="false" use-expressions="true"
		entry-point-ref="loginUrlAuthenticationEntryPoint">

		<custom-filter position="FORM_LOGIN_FILTER"
			ref="customUsernamePasswordAuthenticationFilter" />

		<intercept-url pattern="/" access="hasRole('ROLE_USER')" />

		<intercept-url pattern="/welcome" access="hasRole('ROLE_USER')" />

		<intercept-url pattern="/loadMenuItem" access="hasRole('ROLE_ADMIN1')" />

		<!-- <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error" 
			username-parameter="username" password-parameter="password"/> -->


		<logout logout-success-url="/login?logout" />

		<session-management>
			<concurrency-control max-sessions="2"
				error-if-maximum-exceeded="true" />
		</session-management>

		<session-management invalid-session-url="/login">
			<concurrency-control expired-url="/login" />
		</session-management>


	</http>


	<beans:bean id="loginUrlAuthenticationEntryPoint"
		class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<beans:constructor-arg value="/login" />
	</beans:bean>


	<beans:bean id="customUsernamePasswordAuthenticationFilter"
		class="javaonline.login.service.CustomAuthenticationFilter">
		<beans:property name="authenticationManager" ref="authenticationManager" />
		<!-- When user provides correct username/password and authentication is 
			successful -->
		<beans:property name="authenticationSuccessHandler"
			ref="authenticationSuccessHandler" />
		<beans:property name="authenticationFailureHandler"
			ref="authenticationFailureHandler" />

	</beans:bean>


	<authentication-manager alias="authenticationManager">
		<authentication-provider user-service-ref="userDetailsServiceImpl">
			<password-encoder ref="encoder"></password-encoder>
		</authentication-provider>
	</authentication-manager>

	<beans:bean id="authenticationSuccessHandler"
		class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
		<beans:property name="defaultTargetUrl" value="/welcome" />
	</beans:bean>



	<!--<beans:bean id="authenticationSuccessHandler" class="javaonline.login.service.CustomWebAuthenticationDetailsSource"/> -->

	<beans:bean id="authenticationFailureHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<beans:property name="defaultFailureUrl" value="/login?error" />
	</beans:bean>


	<beans:bean id="userDetailsServiceImpl"
		class="javaonline.login.service.UserDetailsServiceImpl"></beans:bean>


	<beans:bean id="encoder"
		class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
		<beans:constructor-arg name="strength" value="11" />
	</beans:bean>
</beans:beans>

appcontext-data.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- Configure the data source bean -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- Configure the entity manager factory bean -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan">
                <array>
              <value>javaonline.login.model</value>
              <value>javaonline.menu.model</value>
         </array>
         </property>
   
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    
  

<tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!-- Enable annotation driven transaction management -->
    <tx:annotation-driven/>

    <!--
      set the base package of the repository to configure  JPA  
    -->

    <jpa:repositories base-package="javaonline.login.repository"/>

</beans>

appcontext-mvc.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <mvc:annotation-driven/>
    
    <mvc:resources mapping="/resources/**" location="/resources/"/>
    

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>classpath:validation</value>
            </list>
        </property>
    </bean>
    
     <bean id="roleMenuService" class="javaonline.menu.service.RoleMenuServiceImpl"></bean>
     
      <bean id="roleMenuDao" class="javaonline.menu.service.RoleMenuDAO">
   </bean>
  
  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

To run this example,
we need to create necessary database and tables in MySql database server.   Also we need to insert necessary records.
To create mysql database
             create database springtest;
   where springtest is the database name.
Now the database (springtest)  dump is given below  used in this example
use springtest;

-- MySQL dump 10.13  Distrib 5.1.72, for Win64 (unknown)
--
-- Host: localhost    Database: springtest
-- ------------------------------------------------------
-- Server version	5.1.72-community

--
-- Table structure for table `menus`
--

DROP TABLE IF EXISTS `menus`;
CREATE TABLE `menus` (
  `menu_id` int(11) NOT NULL AUTO_INCREMENT,
  `menu_name` varchar(45) DEFAULT NULL,
  `menu_url` varchar(100) DEFAULT NULL,
  `menu_order` smallint(6) DEFAULT '0',
  `role_name` varchar(45) NOT NULL,
  `id` int(11) NOT NULL,
  PRIMARY KEY (`menu_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
--
-- Dumping data for table `menus`
--

LOCK TABLES `menus` WRITE;
INSERT INTO `menus` VALUES (1,'Menu1','/user/loadMenu1',1,'ROLE_USER',4),(2,'Menu2','/user/loadMenu2',2,'ROLE_USER',4);
UNLOCK TABLES;

--
-- Table structure for table `role`
--

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `role`
--

LOCK TABLES `role` WRITE;
INSERT INTO `role` VALUES (4,'ROLE_USER');
UNLOCK TABLES;

--
-- Table structure for table `user`
--

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL,
  `password` varchar(255) DEFAULT NULL,
  `message` varchar(100) DEFAULT NULL,
  `mobile` varchar(10) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

--
-- Dumping data for table `user`
--

LOCK TABLES `user` WRITE;
INSERT INTO `user` VALUES (8,'guest@abc.com','$2a$11$WJKPuchEkDrGalhSvesTZuHSF6EfI9.Re1khieB8IQJnNRlz4oNWa
','Welcome','0000000000');
UNLOCK TABLES;

--
-- Table structure for table `user_role`
--

DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`),
  KEY `fk_user_role_roleid_idx` (`role_id`),
  CONSTRAINT `fk_user_role_roleid` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_user_role_userid` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `user_role`
--

LOCK TABLES `user_role` WRITE;
INSERT INTO `user_role` VALUES (8,4);
UNLOCK TABLES;

Save the above dump in a sql file for eg.  k.sql

To restore the dump, run the below command in the command line.

mysql -u root -p <k.sql

 Now run the above example by accessing the below url
            http://localhost:8080/spinghibernatelogin
In the login page, give the below inputs
email: guest@abc.com
mobile number: 0000000000
password: guest123
You can download the project at  
You can check out the project from  github.com.  Git URL: https://github.com/vkjegan/SpringHibernateLogin

Leave a Reply