📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
- Authentication refers to the process of verifying the user, which is typically done by asking for credentials.
- Authorization refers to the process of verifying whether or not the user is allowed to do a certain activity.
Video Tutorial
Table of Contents
- Spring Security with its autoconfiguration features
- What we’ll build
- Tools and Technologies Used
- Database Design for Role-Based Spring Security
- Creating and Importing a Project
- Packaging Structure
- The pom.xml File
- Create the JPA entities called Users, Roles, and Message
- Spring Data JPA Repository Interface - UserRepository.java
- Spring Data JPA Repository Interface - MessageRepository.java
- UserDetailsService Implementation
- Customized Spring Security Configuration Extending WebSecurityConfigurerAdapter
- Spring WebMVC Configuration
- Spring MVC Controller - HomeController.java
- MySQL Configuration - application.properties
- Implementing the Remember-Me Feature
- Persistent Tokens
- Thymeleaf layout View
- Thymeleaf Login View
- Thymeleaf Userhome View
- Thymeleaf Adminhome View
- Index View
- Sample data for Users and Roles - src/main/resources/data.sql
- Running Application
- Demo
1. Spring Security with its autoconfiguration features
- Enable HTTP basic security
- Register the AuthenticationManager bean with an in-memory store and a single user
- Ignore paths for commonly used static resource locations (such as /css/, /js/, /images/**, etc.)
- Enable common low-level features such as XSS, CSRF, caching, etc.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
security.user.name=admin
security.user.password=secret
security.user.role=USER,ADMIN
2. What we’ll build
3. Tools and Technologies Used
- Spring Boot - 2+
- JDK - 1.8 or later
- Spring Framework - 5+
- Maven - 3.2+
- IDE - Eclipse or Spring Tool Suite (STS)
- MYSQL - 5.1.47
- Spring Security - 5+
- Thymeleaf-Spring5 - 3.0.9 RELEASE
4. Database Design for Role-Based Spring Security
5. Creating and Importing a Project
- Generate: Maven Project
- Java Version: 1.8 (Default)
- Spring Boot:2.7.3
- Group: net.javaguides.springbootsecurity
- Artifact: springboot-thymeleaf-security-demo
- Name: springboot-thymeleaf-security-demo
- Description: springboot-thymeleaf-security-demo
- Package Name : net.javaguides.springbootsecurity
- Packaging: jar (This is the default value)
- Dependencies: Web, JPA, MySQL, DevTools, Security
6. Packaging Structure
7. The pom.xml File
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.javaguides.springbootsecurity</groupId>
<artifactId>springboot-thymeleaf-security-demo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
8. Create the JPA entities - User, Role, and Message
User JPA Entity
package net.javaguides.springbootsecurity.entities;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
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.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
/**
* @author Ramesh Fadatare
*
*/
@Entity
@Table(name="users")
public class User
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@Column(nullable=false)
@NotEmpty()
private String name;
@Column(nullable=false, unique=true)
@NotEmpty
@Email(message="{errors.invalid_email}")
private String email;
@Column(nullable=false)
@NotEmpty
@Size(min=4)
private String password;
@ManyToMany(cascade=CascadeType.MERGE)
@JoinTable(
name="user_role",
joinColumns={@JoinColumn(name="USER_ID", referencedColumnName="ID")},
inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="ID")})
private List<Role> roles;
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public List<Role> getRoles()
{
return roles;
}
public void setRoles(List<Role> roles)
{
this.roles = roles;
}
}
Role JPA Entity
package net.javaguides.springbootsecurity.entities;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.validator.constraints.NotEmpty;
/**
* @author Ramesh Fadatare
*
*/
@Entity
@Table(name = "roles")
public class Role {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(nullable = false, unique = true)
@NotEmpty
private String name;
@ManyToMany(mappedBy = "roles")
private List < User > users;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List < User > getUsers() {
return users;
}
public void setUsers(List < User > users) {
this.users = users;
}
}
package net.javaguides.springbootsecurity.entities;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.validator.constraints.NotEmpty;
/**
* @author Ramesh Fadatare
*
*/
@Entity
@Table(name = "roles")
public class Role {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(nullable = false, unique = true)
@NotEmpty
private String name;
@ManyToMany(mappedBy = "roles")
private List < User > users;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List < User > getUsers() {
return users;
}
public void setUsers(List < User > users) {
this.users = users;
}
}
Message JPA Entity
package net.javaguides.springbootsecurity.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Ramesh Fadatare
*
*/
@Entity
@Table(name = "messages")
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(nullable = false)
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
9. Spring Data JPA Repository Interface - UserRepository.java
package net.javaguides.springbootsecurity.repositories;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import net.javaguides.springbootsecurity.entities.User;
/**
* @author Ramesh Fadatare
*
*/
public interface UserRepository extends JpaRepository<User, Integer>
{
Optional<User> findByEmail(String email);
}
10. Spring Data JPA Repository Interface - MessageRepository.java
package net.javaguides.springbootsecurity.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import net.javaguides.springbootsecurity.entities.Message;
/**
* @author Ramesh Fadatare
*
*/
public interface MessageRepository extends JpaRepository<Message, Integer>{
}
11. UserDetailsService Implementation
package net.javaguides.springbootsecurity.security;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import net.javaguides.springbootsecurity.entities.User;
import net.javaguides.springbootsecurity.repositories.UserRepository;
/**
* @author Ramesh Fadatare
*
*/
@Service
@Transactional
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userRepository.findByEmail(userName)
.orElseThrow(() -> new UsernameNotFoundException("Email " + userName + " not found"));
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(),
getAuthorities(user));
}
private static Collection<? extends GrantedAuthority> getAuthorities(User user) {
String[] userRoles = user.getRoles().stream().map((role) -> role.getName()).toArray(String[]::new);
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(userRoles);
return authorities;
}
}
12. Customized Spring Security Configuration Extending WebSecurityConfigurerAdapter
package net.javaguides.springbootsecurity.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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
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 org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService customUserDetailsService;
@Autowired
private DataSource dataSource;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.frameOptions().sameOrigin()
.and()
.authorizeRequests()
.antMatchers("/resources/**", "/webjars/**","/assets/**").permitAll()
.antMatchers("/").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.failureUrl("/login?error")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.deleteCookies("my-remember-me-cookie")
.permitAll()
.and()
.rememberMe()
//.key("my-secure-key")
.rememberMeCookieName("my-remember-me-cookie")
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(24 * 60 * 60)
.and()
.exceptionHandling()
;
}
PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
}
- Ignore the static resource paths "/resources/", "/webjars/", and "/assets/**"
- Allow everyone to have access to the root URL "/"
- Restrict access to URLs that start with /admin/ to only users with the ADMIN role
- All other URLs should be accessible to authenticated users only
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
13. Spring WebMVC Configuration
package net.javaguides.springbootsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
/**
* @author Ramesh Fadatare
*
*/
@Configuration
public class WebConfig implements WebMvcConfigurer
{
@Autowired
private MessageSource messageSource;
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/").setViewName("index");
registry.addViewController("/login").setViewName("login");
//registry.addViewController("/home").setViewName("userhome");
registry.addViewController("/admin/home").setViewName("adminhome");
//registry.addViewController("/403").setViewName("403");
}
@Override
public Validator getValidator() {
LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
factory.setValidationMessageSource(messageSource);
return factory;
}
@Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
}
14. Spring MVC Controller - HomeController.java
package net.javaguides.springbootsecurity.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import net.javaguides.springbootsecurity.entities.Message; import net.javaguides.springbootsecurity.repositories.MessageRepository; /** * @author Ramesh Fadatare * */ @Controller public class HomeController { @Autowired private MessageRepository messageRepository; @GetMapping("/home") public String home(Model model) { model.addAttribute("msgs", messageRepository.findAll()); return "userhome"; } @PostMapping("/messages") public String saveMessage(Message message) { messageRepository.save(message); return "redirect:/home"; } }
15. MySQL Configuration - application.properties
################### DataSource Configuration ##########################
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.initialization-mode=always
################### Hibernate Configuration ##########################
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
#security.user.name=admin
#security.user.password=secret
#security.user.role=USER,ADMIN
16. Implementing the Remember-Me Feature
<input type="checkbox" name="remember-me"> Remember Me
- Simple hash-based token as a cookie —This approach creates a token by hashing the user identity information and setting it as a cookie on the client browser.
- Persistent token —This approach uses a persistent store like a relational database to store the tokens.
17. Persistent Tokens
- InMemoryTokenRepositoryImpl can be used to store tokens in-memory (not recommended for production use).
- JdbcTokenRepositoryImpl can be used to store tokens in a database.
persistent_logins table
create table persistent_logins
(
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
18. Thymeleaf layout View
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">SpringBoot
Thymeleaf</title>
<meta
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
name="viewport" />
<link rel="stylesheet"
th:href="@{/assets/bootstrap/css/bootstrap.min.css}" />
<link rel="stylesheet"
th:href="@{/assets/font-awesome-4.5.0/css/font-awesome.min.css}" />
<link rel="stylesheet" th:href="@{/assets/css/styles.css}" />
<style>
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: black;
color: white;
height: 100px;
text-align: center;
}
</style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar" aria-expanded="false"
aria-controls="navbar">
<span class="sr-only">Toggle navigation</span> <span
class="icon-bar"></span> <span class="icon-bar"></span> <span
class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#" th:href="@{/}">SpringBoot
Thymeleaf</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li sec:authorize="isAuthenticated()"><a th:href="@{/logout}">Logout</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div layout:fragment="content">
<!-- Your Page Content Here -->
</div>
</div>
<script th:src="@{'/assets/js/jquery-2.1.4.min.js'}"></script>
<script th:src="@{'/assets/bootstrap/js/bootstrap.min.js'}"></script>
<div class="footer">
<h1>
<a href="http://www.javaguides.net/p/spring-boot-tutorial.html">
Spring Boot Tutorial</a>
</h1>
</div>
</body>
</html>
19. Thymeleaf Login View
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
layout:decorator="layout">
<head>
<title>Log in</title>
</head>
<body>
<div layout:fragment="content">
<div class="panel col-md-5">
<div class="panel panel-primary">
<div class="panel-heading">Login Form</div>
<div class="panel-body">
<form action="home" th:action="@{/login}" method="post">
<div class="form-group has-feedback">
<input type="email" class="form-control" name="username"
placeholder="Email" /> <span
class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" class="form-control" name="password"
placeholder="Password" /> <span
class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="remember-me"> Remember Me
</label>
</div>
<div class="row">
<div class="form-group col-xs-offset-8 col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat"
th:text="#{label.login}">LogIn</button>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div th:if="${param.error}"
class="alert alert-danger alert-dismissable">
<p>
<i class="icon fa fa-ban"></i> <span
th:text="#{error.login_failed}">Invalid Email and
Password.</span>
</p>
</div>
<div th:if="${param.logout}"
class="alert alert-info alert-dismissable">
<p>
<i class="icon fa fa-info"></i> <span
th:text="#{info.logout_success}">You have been logged
out.</span>
</p>
</div>
<div th:if="${msg!=null}"
class="alert alert-warning alert-dismissable">
<p>
<i class="icon fa fa-warning"></i> <span th:text="${msg}"></span>
</p>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
20. Thymeleaf Userhome View
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
layout:decorator="layout">
<head>
<title>User Home</title>
</head>
<body>
<div layout:fragment="content">
<p>
Welcome <span sec:authentication="principal.username">User</span>
</p>
<p>
<a th:href="@{/logout}">Logout</a>
</p>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<h3>You will see this only if you are ADMIN</h3>
<p>
<a th:href="@{/admin/home}">Admin Home</a>
</p>
</div>
<h3>Form with CSRF Token</h3>
<form th:action="@{/messages}" method="post">
<textarea name="content" cols="50" rows="5"></textarea>
<br>
<input type="submit" value="Submit" />
</form>
<div>
<br>
<div class="panel panel-default">
<div class="panel-heading">
Messages
</div>
<p th:each="msg: ${msgs}" th:text="${msg.content}"></p>
</div>
</div>
</div>
</body>
</html>
21. Thymeleaf Adminhome View
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
layout:decorator="layout">
<head>
<title>Admin Home</title>
</head>
<body>
<div layout:fragment="content">
<p>Welcome Administrator(<span sec:authentication="principal.username">Admin</span>)</p>
<p sec:authorize="isAuthenticated()"><a th:href="@{/logout}">Logout</a></p>
</div>
<h1>This is admin home page</h1>
</body>
</html>
22. Index View
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
layout:decorator="layout">
<head>
<title>Home</title>
</head>
<body>
<div layout:fragment="content">
<p sec:authorize="isAnonymous()"><a th:href="@{/login}">Login</a></p>
<p><a th:href="@{/home}">User Home</a></p>
<p><a th:href="@{/admin/home}">Admin Home</a></p>
<p sec:authorize="isAuthenticated()"><a th:href="@{/logout}">Logout</a></p>
</div>
</body>
</html>
23. Sample data for Users and Roles - src/main/resources/data.sql
create table if not exists persistent_logins (
username varchar(100) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
delete from user_role;
delete from roles;
delete from users;
INSERT INTO roles (id, name) VALUES
(1, 'ROLE_ADMIN'),
(2, 'ROLE_ACTUATOR'),
(3, 'ROLE_USER');
INSERT INTO users (id, email, password, name) VALUES
(1, '[email protected]', '$2a$10$hKDVYxLefVHV/vtuPhWD3OigtRyOykRLDdUAp80Z1crSoS1lFqaFS', 'Admin'),
(3, '[email protected]', '$2a$10$ByIUiNaRfBKSV6urZoBBxe4UbJ/sS6u1ZaPORHF9AtNWAuVPVz1by', 'User');
insert into user_role(user_id, role_id) values
(1,1),
(1,2),
(1,3),
(3,2);
24. Running Application
- From the root directory of the application and type the following command to run it -
$ mvn spring-boot:run
- From your IDE, run the SpringbootThymeleafSecurityDemoApplication.main() method as a standalone Java class that will start the embedded Tomcat server on port 8080 and point the browser to http://localhost:8080/.
package net.javaguides.springbootsecurity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootThymeleafSecurityDemoApplication
{
public static void main(String[] args)
{
SpringApplication.run(SpringbootThymeleafSecurityDemoApplication.class, args);
}
}
25. Demo
Click on the logout link will redirect to the login page with the proper message:
hello!
ReplyDeleteI enjoyed your post Spring Boot + Spring MVC + Role Based Spring Security + JPA + Thymeleaf + MySQL Tutorial.
something seemed to be different from the site tutorial, because It´s missing the AuthenticatedUser class in the security package and the web package was not mentioned in the tutorial,
I've been in your github repository I downloaded it, but when I run the project show up 404 error - Whitelabel Error Page.
Can you confirm if this project that is in github is running 100%?
Thanks for pointing missing web package and i added missing part. The AuthenticatedUser class is not needed to run this project. I confirmed this project should work. Please following urls and let me know if you face any issues.
DeleteI got error. Error creating bean with name 'entityManagerFactory' defined in class path resource I tried every resolution posted online but nothing works.
ReplyDeleteclone github repository of this tutorial (given link at end of this tutorial) and try to build maven spring boot project successfully should work. Plz re-check database configuration and MySQL setup.
DeleteHi.
ReplyDeleteThanks a lot ; it's a very nice tutorial.
Cheers.
Thanks a lot, it really helps a lot. However, how do I create a register page for the system?
ReplyDeleteHi Ramesh Fadatare,Thanks for the tutorial,I found your tutorial very useful,but my problem is it is authenticating only using username or email it is ignoring password validation can please expline about this issue.Thank you.
ReplyDeletegreat sir 100/100 thanks for the help can you pleas give you mail we have some opportunity some business related you can mail me at [email protected]
ReplyDeletegreat sir 100/100 thanks for the help can you pleas give you mail we have some opportunity some business related you can mail me at [email protected]
ReplyDeletejava.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer
ReplyDeleteI am getting the above error when trying to run a my project. Kindly help
Thank you so very much! good job! .. I followed your steps! and it is working for me
ReplyDeleteHi Sir
ReplyDelete**A SERIOUS BUG**
Try to login with 1 user and 1 admin in two tabs of the same browser window or login in 2 new windows and see the changes happend in 1 window/tab is effecting in another window. plz check and fix the problem. ITS A SERIOUS BUG.
Thanking you.
see https://github.com/caiofernandomf/springboot-thymeleaf-security-demo
Delete