Information Security 19 min read

Spring Security Based System Permission Management Tutorial

This article provides a comprehensive step‑by‑step guide on building a permission management system with Spring Security, covering database design, entity classes, Maven configuration, security configuration, dynamic menu loading, front‑end rendering using Thymeleaf, and complete testing with sample code and screenshots.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Spring Security Based System Permission Management Tutorial

System Permission Management

In real‑world development, permission management is essential; this guide demonstrates a complete solution based on Spring Security, which offers high security and password encryption.

Technology Stack

The project uses Spring Boot, Spring Security, Spring Data JPA, Thymeleaf for templating, Bootstrap for UI, and MySQL as the database.

Database Design

Four tables are defined:

Menu ( TbMenu ) – stores all menus displayed on the page.

Role ( SysRole ) – stores roles and the menus they can access.

User ( SysUser ) – stores user credentials.

User‑Role mapping ( sys_user_role ) – many‑to‑many relationship generated by Spring Data JPA.

Project Setup

Create a Spring Boot project and add the following Maven dependencies (pom.xml):

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>
    <groupId>com.mcy</groupId>
    <artifactId>springboot-security</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- other dependencies omitted for brevity -->
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Entity Classes

Menu entity ( TbMenu ) with parent‑child relationship:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mcy.springbootsecurity.custom.BaseEntity;
import org.springframework.data.annotation.CreatedBy;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class TbMenu extends BaseEntity
{
    private String name;
    private String url;
    private Integer idx;
    @JsonIgnore
    private TbMenu parent;
    @JsonIgnore
    private List
children = new ArrayList<>();
    // getters, setters, constructors omitted for brevity
}

Role entity ( SysRole ) stores role name, code and hierarchical permissions:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mcy.springbootsecurity.custom.BaseEntity;
import org.springframework.data.annotation.CreatedBy;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class SysRole extends BaseEntity
{
    private String name;
    private String code;
    @JsonIgnore
    private SysRole parent;
    private Integer idx;
    @JsonIgnore
    private List
children = new ArrayList<>();
    // getters, setters, constructors omitted for brevity
}

User entity ( SysUser ) with many‑to‑many relationship to roles:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mcy.springbootsecurity.custom.BaseEntity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class SysUser extends BaseEntity
{
    private String username;
    private String password;
    private String name;
    private String address;
    @JsonIgnore
    private List
roles = new ArrayList<>();
    // getters, setters, transient fields for role names/codes omitted for brevity
}

Security Configuration

Configure authentication and authorization in WebSecurityConfig :

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SysUserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("aaa").password("{noop}1234").roles("DIY");
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.formLogin()
            .loginPage("/login").permitAll()
            .successForwardUrl("/main")
            .failureUrl("/login?error");
        http.authorizeRequests().antMatchers("/static/**", "/assets/**", "/webjars/**").permitAll();
        http.logout().logoutUrl("/logout").permitAll();
        http.authorizeRequests().anyRequest().authenticated();
    }
}

Utility Class

UserUtils obtains the currently logged‑in user and checks role membership:

@Component
public class UserUtils {
    @Autowired
    private SysUserService userService;

    public SysUser getUser() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        return userService.findByUsername(username);
    }

    public Boolean hasRole(String roleName) {
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List
roleCodes = new ArrayList<>();
        for (GrantedAuthority authority : userDetails.getAuthorities()) {
            roleCodes.add(authority.getAuthority());
        }
        return roleCodes.contains(roleName);
    }
}

Dynamic Permission Menu Loading

Implement loadUserByUsername to build UserDetails with authorities derived from roles and their child permissions, then filter menus based on those authorities in TbMenuService.findAuditMenu and auditMenu methods.

Front‑End Menu Rendering

Use Thymeleaf together with LayUI to iterate over the menu list and render collapsible panels. Example snippet:

<div th:each="menu, menuStat : ${menus}" th:if="${menu.children.size() != 0}" class="panel panel-default">
    <div class="panel-heading">
        <h4 class="panel-title">
            <p data-toggle="collapse" data-parent="#accordion" th:href="|#collapseOne${menuStat.index}|">
                <span th:text="${menu.name}">系统设置</span><span class="caret"></span>
            </p>
        </h4>
    </div>
    <div th:id="|collapseOne${menuStat.index}|" class="panel-collapse collapse">
        <div class="panel-body">
            <p th:each="subMenu : ${menu.children}" th:src="${subMenu.url}" th:text="${subMenu.name}">菜单管理</p>
        </div>
    </div>
</div>

Testing and Results

Sample users (admin1, admin2, admin3) demonstrate different role‑based menu displays. Screenshots show menu trees for administrators, regular users, and test users, confirming that the permission filtering works as expected.

Download

The complete source code is available at https://github.com/machaoyin/SpringBoot-Security .

backendJavaSpring BootAuthenticationPermission ManagementauthorizationSpring Security
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.