构建一个完整的基于Spring Boot的权限管理系统是一个庞大的任务,涉及多个模块和复杂的业务逻辑。由于代码量较大,我将提供一个简化版本的框架结构,并详细解释每个部分的关键实现。你可以根据需要进一步扩展和完善这个系统。
项目结构
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── demo
│ │ ├── controller
│ │ │ ├── UserController.java
│ │ │ ├── RoleController.java
│ │ │ ├── OrganizationController.java
│ │ │ ├── MenuController.java
│ │ │ ├── AuthController.java
│ │ │ └── PermissionController.java
│ │ ├── service
│ │ │ ├── UserService.java
│ │ │ ├── RoleService.java
│ │ │ ├── OrganizationService.java
│ │ │ ├── MenuService.java
│ │ │ ├── PermissionService.java
│ │ │ ├── AuthService.java
│ │ │ └── impl
│ │ │ ├── UserServiceImpl.java
│ │ │ ├── RoleServiceImpl.java
│ │ │ ├── OrganizationServiceImpl.java
│ │ │ ├── MenuServiceImpl.java
│ │ │ ├── PermissionServiceImpl.java
│ │ │ └── AuthServiceImpl.java
│ │ ├── mapper
│ │ │ ├── UserMapper.java
│ │ │ ├── RoleMapper.java
│ │ │ ├── OrganizationMapper.java
│ │ │ ├── MenuMapper.java
│ │ │ ├── PermissionMapper.java
│ │ │ └── AuthMapper.java
│ │ ├── config
│ │ │ ├── JwtConfig.java
│ │ │ └── SecurityConfig.java
│ │ └── DemoApplication.java
│ └── resources
│ ├── application.properties
│ ├── mapper
│ │ ├── UserMapper.xml
│ │ ├── RoleMapper.xml
│ │ ├── OrganizationMapper.xml
│ │ ├── MenuMapper.xml
│ │ ├── PermissionMapper.xml
│ │ └── AuthMapper.xml
│ └── static
└── test
└── java
└── com
└── example
└── demo
└── DemoApplicationTests.java
核心依赖 (pom.xml)
确保你的pom.xml
文件中包含以下核心依赖:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Lombok for less boilerplate code -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
配置文件 (application.properties)
# MySQL Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis Configuration
mybatis.mapper-locations=classpath:mapper/*.xml
# JWT Configuration
jwt.secret=yourSecretKey
jwt.expiration=86400 # seconds
JWT配置 (JwtConfig.java)
package com.example.demo.config;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtConfig {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Claims getClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
}
安全配置 (SecurityConfig.java)
package com.example.demo.config;
import com.example.demo.service.impl.AuthServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthServiceImpl authService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
实体类
用户实体 (User.java)
package com.example.demo.model;
import lombok.Data;
@Data
public class User {
private Long id;
private String username;
private String password;
private String email;
private Long roleId;
}
角色实体 (Role.java)
package com.example.demo.model;
import lombok.Data;
@Data
public class Role {
private Long id;
private String name;
private String description;
}
组织机构实体 (Organization.java)
package com.example.demo.model;
import lombok.Data;
@Data
public class Organization {
private Long id;
private String name;
private String description;
}
菜单实体 (Menu.java)
package com.example.demo.model;
import lombok.Data;
@Data
public class Menu {
private Long id;
private String name;
private String url;
private Long parentId;
}
权限实体 (Permission.java)
package com.example.demo.model;
import lombok.Data;
@Data
public class Permission {
private Long id;
private String name;
private String code;
}
Mapper接口及XML配置
为每个实体创建对应的Mapper接口和XML配置文件(如UserMapper.java
、UserMapper.xml
等),并定义相应的CRUD方法。
示例:UserMapper.java 和 UserMapper.xml
package com.example.demo.mapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.*;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectById(Long id);
// ... other CRUD methods
}
<!-- src/main/resources/mapper/UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
<!-- Additional SQL mappings can be added here if needed -->
</mapper>
Service接口及实现
为每个实体创建服务接口和服务实现类(如UserService.java
、UserServiceImpl.java
等),并实现业务逻辑。
示例:UserServiceImpl.java
package com.example.demo.service.impl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(Long id) {
return userMapper.selectById(id);
}
// ... other service methods
}
控制器 (Controllers)
为每个功能模块创建控制器,处理HTTP请求,并调用对应的服务层方法。
示例:UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.updateUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
为了实现权限管理功能,我们将创建PermissionController.java
、PermissionService.java
、PermissionServiceImpl.java
和PermissionMapper.java
。这些组件将负责处理权限的创建、读取、更新和删除(CRUD)操作。
PermissionController.java
这个控制器将处理与权限相关的HTTP请求。它将调用服务层的方法来执行具体的操作。
package com.example.demo.controller;
import com.example.demo.model.Permission;
import com.example.demo.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/permissions")
public class PermissionController {
@Autowired
private PermissionService permissionService;
@GetMapping
public List<Permission> getAllPermissions() {
return permissionService.getAllPermissions();
}
@GetMapping("/{id}")
public Permission getPermissionById(@PathVariable Long id) {
return permissionService.getPermissionById(id);
}
@PostMapping
public Permission createPermission(@RequestBody Permission permission) {
return permissionService.createPermission(permission);
}
@PutMapping("/{id}")
public Permission updatePermission(@PathVariable Long id, @RequestBody Permission permissionDetails) {
return permissionService.updatePermission(id, permissionDetails);
}
@DeleteMapping("/{id}")
public void deletePermission(@PathVariable Long id) {
permissionService.deletePermission(id);
}
}
PermissionService.java
服务接口定义了权限管理所需的所有业务逻辑方法。
package com.example.demo.service;
import com.example.demo.model.Permission;
import java.util.List;
public interface PermissionService {
List<Permission> getAllPermissions();
Permission getPermissionById(Long id);
Permission createPermission(Permission permission);
Permission updatePermission(Long id, Permission permission);
void deletePermission(Long id);
}
PermissionServiceImpl.java
这是服务接口的具体实现类,包含了权限管理的实际业务逻辑。
package com.example.demo.service.impl;
import com.example.demo.mapper.PermissionMapper;
import com.example.demo.model.Permission;
import com.example.demo.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PermissionServiceImpl implements PermissionService {
@Autowired
private PermissionMapper permissionMapper;
@Override
public List<Permission> getAllPermissions() {
return permissionMapper.selectAllPermissions();
}
@Override
public Permission getPermissionById(Long id) {
return permissionMapper.selectPermissionById(id);
}
@Override
public Permission createPermission(Permission permission) {
permissionMapper.insertPermission(permission);
return permission;
}
@Override
public Permission updatePermission(Long id, Permission permissionDetails) {
Permission updatedPermission = permissionMapper.selectPermissionById(id);
if (updatedPermission != null) {
// 更新权限信息
updatedPermission.setName(permissionDetails.getName());
updatedPermission.setCode(permissionDetails.getCode());
permissionMapper.updatePermission(updatedPermission);
}
return updatedPermission;
}
@Override
public void deletePermission(Long id) {
permissionMapper.deletePermissionById(id);
}
}
PermissionMapper.java
MyBatis Mapper接口用于定义对数据库中权限表的操作。请注意,你还需要为这个接口编写对应的XML映射文件(PermissionMapper.xml
),以提供具体的SQL语句。
package com.example.demo.mapper;
import com.example.demo.model.Permission;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface PermissionMapper {
@Select("SELECT * FROM permissions")
List<Permission> selectAllPermissions();
@Select("SELECT * FROM permissions WHERE id = #{id}")
Permission selectPermissionById(Long id);
@Insert("INSERT INTO permissions(name, code) VALUES(#{name}, #{code})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertPermission(Permission permission);
@Update("UPDATE permissions SET name=#{name}, code=#{code} WHERE id=#{id}")
void updatePermission(Permission permission);
@Delete("DELETE FROM permissions WHERE id=#{id}")
void deletePermissionById(Long id);
}
PermissionMapper.xml
在src/main/resources/mapper/PermissionMapper.xml
中添加以下内容:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.PermissionMapper">
<!-- You can define additional SQL mappings here if needed -->
</mapper>
### 数据库表结构
你需要在MySQL数据库中创建多个表来存储用户、角色、组织机构、菜单和权限的信息。以下是简化版的SQL语句:
```sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(255),
role_id BIGINT
);
CREATE TABLE roles (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT
);
CREATE TABLE organizations (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT
);
CREATE TABLE menus (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
url VARCHAR(255),
parent_id BIGINT
);
CREATE TABLE permissions (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
code VARCHAR(255)
);
-- 创建关联表
CREATE TABLE user_roles (
user_id BIGINT,
role_id BIGINT,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);
CREATE TABLE role_permissions (
role_id BIGINT,
permission_id BIGINT,
FOREIGN KEY (role_id) REFERENCES roles(id),
FOREIGN KEY (permission_id) REFERENCES permissions(id)
);
启动类 (DemoApplication.java)
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Token认证过滤器
JwtAuthenticationFilter.java 和 JwtAuthorizationFilter.java
package com.example.demo.config;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtConfig jwtConfig;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
try {
String token = parseJwt(request);
if (token != null && jwtConfig.getClaimsFromToken(token) != null) {
Claims claims = jwtConfig.getClaimsFromToken(token);
String username = claims.getSubject();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
return;
}
chain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (headerAuth != null && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
}
// JwtAuthorizationFilter would extend OncePerRequestFilter and handle authorization logic.
总结
以上代码片段展示了如何构建一个基于Spring Boot的权限管理系统,包括用户管理、角色管理、组织机构管理、菜单管理和权限管理等功能。通过这些组件,你可以实现对用户的注册、登录、信息修改以及权限分配等操作。此外,系统还支持通过JWT进行Token认证,确保了安全性。
请注意,这只是一个基础框架,实际应用中可能还需要添加更多的特性,如输入验证、异常处理、日志记录等。同时,考虑到系统的复杂性,建议逐步开发各个模块,并进行充分的测试以保证系统的稳定性和可靠性。如果你有更具体的需求或想要进一步细化某些部分,请告诉我!