Create View
Create new folders with path webapp\WEB-INF\views in src\main. In views folder, create new JSP Pages as below:
Home View
Create new folder named home. Create new jsp file named index.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home Page</title>
</head>
<body>
<h3>Home Page</h3>
</body>
</html>
SuperAdmin Views
Create new folder named superadmin. In this folder, create new views as below:
Index View
Create new jsp file named index.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home Page of SuperAdmin Panel</title>
</head>
<body>
<h3>Home Page of SuperAdmin Panel</h3>
</body>
</html>
Login View
Create new jsp file named login.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login to SuperAdmin Panel</title>
</head>
<body>
<h3>Login to SuperAdmin Area</h3>
${msg }
<form method="post"
action="${pageContext.request.contextPath }/superadmin/process-login">
<table cellpadding="2" cellspacing="2">
<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> </td>
<td><input type="submit" value="Login"></td>
</tr>
</table>
</form>
</body>
</html>
Welcome View
Create new jsp file named welcome.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome to SuperAdmin Panel</title>
</head>
<body>
<h3>SuperAdmin Panel</h3>
Welcome ${pageContext.request.userPrincipal.name}
<br>
<a href="${pageContext.request.contextPath }/superadmin-panel/logout">Logout</a>
</body>
</html>
AccessDenied View
Create new jsp file named accessDenied.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access Denied</title>
</head>
<body>
<h3>Access Denied to SuperAdmin Panel</h3>
${msg }
<br>
<a href="${pageContext.request.contextPath }/superadmin-panel/welcome">Back</a>
</body>
</html>
Admin Views
Create new folder named admin. In this folder, create new views as below:
Index View
Create new jsp file named index.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home Page of Admin Panel</title>
</head>
<body>
<h3>Home Page of Admin Panel</h3>
</body>
</html>
Login View
Create new jsp file named login.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login to Admin Panel</title>
</head>
<body>
<h3>Login to Admin Panel</h3>
${msg }
<form method="post"
action="${pageContext.request.contextPath }/admin/process-login">
<table cellpadding="2" cellspacing="2">
<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> </td>
<td><input type="submit" value="Login"></td>
</tr>
</table>
</form>
</body>
</html>
Welcome View
Create new jsp file named welcome.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access Denied</title>
</head>
<body>
<h3>Access Denied to Admin Panel</h3>
${msg }
<br>
<a href="${pageContext.request.contextPath }/admin-panel/welcome">Back</a>
</body>
</html>
AccessDenied View
Create new jsp file named accessDenied.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access Denied</title>
</head>
<body>
<h3>Access Denied to Admin Panel</h3>
${msg }
<br>
<a href="${pageContext.request.contextPath }/admin-panel/welcome">Back</a>
</body>
</html>
Employee Views
Create new folder named employee. In this folder, create new views as below:
Index View
Create new jsp file named index.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home Page of Employee Panel</title>
</head>
<body>
<h3>Home Page of Employee Panel</h3>
</body>
</html>
Login View
Create new jsp file named login.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login to Employee Panel</title>
</head>
<body>
<h3>Login to Employee Panel</h3>
${msg }
<form method="post"
action="${pageContext.request.contextPath }/employee/process-login">
<table cellpadding="2" cellspacing="2">
<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> </td>
<td><input type="submit" value="Login"></td>
</tr>
</table>
</form>
</body>
</html>
Welcome View
Create new jsp file named welcome.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome to Employee Panel</title>
</head>
<body>
<h3>Employee Panel</h3>
Welcome ${pageContext.request.userPrincipal.name}
<br>
<a href="${pageContext.request.contextPath }/employee-panel/logout">Logout</a>
</body>
</html>
AccessDenied View
Create new jsp file named accessDenied.jsp as below:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access Denied</title>
</head>
<body>
<h3>Access Denied to Employee Panel</h3>
${msg }
<br>
<a href="${pageContext.request.contextPath }/employee-panel/welcome">Back</a>
</body>
</html>
Security Configurations
In com.demo package, create configurations for Spring Security as below:
SuperAdmin Security Configuration
Create new java class named SuperAdminSecurityConfiguration.java as below:
package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import com.demo.services.UserService;
@EnableWebSecurity
@Configuration
@Order(1)
public class SuperAdminSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and().csrf().disable();
httpSecurity.antMatcher("/superadmin/**")
.authorizeRequests()
.antMatchers("/superadmin/**").access("hasRole('ROLE_SUPER_ADMIN')")
.and()
.formLogin().loginPage("/superadmin-panel")
.loginProcessingUrl("/superadmin/process-login")
.defaultSuccessUrl("/superadmin-panel/welcome")
.failureUrl("/superadmin-panel/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutUrl("/superadmin-panel/process-logout")
.logoutSuccessUrl("/superadmin-panel/login?logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.exceptionHandling().accessDeniedPage("/superadmin-panel/accessDenied");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService);
}
@Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityContextHolderAwareRequestFilter awareRequestFilter() {
return new SecurityContextHolderAwareRequestFilter();
}
@Bean
public SecurityContextPersistenceFilter persistenceFilter() {
return new SecurityContextPersistenceFilter();
}
}
Admin Security Configuration
Create new java class named AdminSecurityConfiguration.java as below:
package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import com.demo.services.UserService;
@EnableWebSecurity
@Configuration
@Order(2)
public class AdminSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and().csrf().disable();
httpSecurity.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/admin-panel")
.loginProcessingUrl("/admin/process-login")
.defaultSuccessUrl("/admin-panel/welcome")
.failureUrl("/admin-panel/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutUrl("/admin-panel/process-logout")
.logoutSuccessUrl("/admin-panel/login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling().accessDeniedPage("/admin-panel/accessDenied");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService);
}
@Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityContextHolderAwareRequestFilter awareRequestFilter() {
return new SecurityContextHolderAwareRequestFilter();
}
@Bean
public SecurityContextPersistenceFilter persistenceFilter() {
return new SecurityContextPersistenceFilter();
}
}
Employee Security Configuration
Create new java class named EmployeeSecurityConfiguration.java as below:
package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import com.demo.services.UserService;
@EnableWebSecurity
@Configuration
@Order(3)
public class EmployeeSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and().csrf().disable();
httpSecurity.antMatcher("/employee/**")
.authorizeRequests()
.antMatchers("/employee/**").access("hasRole('ROLE_EMPLOYEE')")
.and()
.formLogin().loginPage("/employee-panel")
.loginProcessingUrl("/employee/process-login")
.defaultSuccessUrl("/employee-panel/welcome")
.failureUrl("/employee-panel/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutUrl("/employee-panel/process-logout")
.logoutSuccessUrl("/employee-panel/login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling().accessDeniedPage("/employee-panel/accessDenied");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService);
}
@Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityContextHolderAwareRequestFilter awareRequestFilter() {
return new SecurityContextHolderAwareRequestFilter();
}
@Bean
public SecurityContextPersistenceFilter persistenceFilter() {
return new SecurityContextPersistenceFilter();
}
}
Structure of Project
Run Application
Select LearnSpringMVCWithRealAppsApplication.java file in com.demo package, right click and select Run As/Spring Boot App menu
Access index method in home controller with following url: http://localhost:9596/home
Output
SuperAdmin Panel
-
Test access index action in superadmin controller without account with url: http://localhost:9596/superadmin
Output
-
Test login with invalid account: username is abc and password is 123
Output
-
Test login with valid account: username is acc1 and password is 123. This account have roles: ROLE_SUPER_ADMIN, ROLE_ADMIN and ROLE_EMPLOYEE
Output
-
Test access index action in superadmin controller again with url: http://localhost:9596/superadmin
Output
-
Test access index action in admin controller with url: http://localhost:9596/admin
Output
-
Test access index action in employee controller with url: http://localhost:9596/employee
Output
Admin Panel
-
Test access index action in admin controller without account with url: http://localhost:9596/admin
Output
-
Test login with invalid account: username is abc and password is 123
Output
-
Test login with valid account: username is acc2 and password is 123. This account have roles: ROLE_ADMIN and ROLE_EMPLOYEE
Output
-
Test access index action in admin controller again with url: http://localhost:9596/admin
Output
-
Test access index action in superadmin controller with url: http://localhost:9596/superadmin
Output
-
Test access index action in employee controller with url: http://localhost:9596/employee
Output
Employee Panel
-
Test access index action in employee controller without account with url: http://localhost:9596/employee
Output
-
Test login with invalid account: username is abc and password is 123
Output
-
Test login with valid account: username is acc3 and password is 123. This account have roles: ROLE_EMPLOYEE
Output
-
Test access index action in employee controller again with url: http://localhost:9596/employee
Output
-
Test access index action in superadmin controller with url: http://localhost:9596/superadmin
Output
-
Test access index action in admin controller with url: http://localhost:9596/admin
Output
References
I recommend you refer to the books below to learn more about the knowledge in this article:
- Spring MVC Beginners Guide – Second Edition
- Spring Boot in Action
- Pro Spring Boot
- Spring Data
- Spring Security – Third Edition: Secure your web applications, RESTful services, and microservice architectures
- Spring Security Essentials
- OAuth 2.0 Cookbook: Protect your web applications using Spring Security
- Pro Spring Security