角色权限控制(RBAC)与动态菜单
2026/8/24 9:06:47 网站建设 项目流程

角色权限控制(RBAC)与动态菜单

实验目的

1.理解 RBAC(基于角色的访问控制)模型。
2.掌握用户-角色-权限的关系设计。
3.掌握基于 JWT 的权限控制实现方式。
4.实现接口权限校验(不同角色访问不同接口)。
5.实现动态菜单(根据权限返回菜单数据)。

实验环境

开发工具:IntelliJ IDEA

构建工具:Maven

测试工具:Postman或浏览器

AI工具:通义灵码

实验要求

在校园二手交易系统中实现权限控制功能:

1.实现用户、角色、权限三张核心表
2.登录后返回用户角色信息
3.不同角色访问不同接口
4.实现动态菜单接口(按权限返回)
5.未授权访问返回错误信息

实验内容

第一部分:RBAC模型设计

RBAC 核心关系:

用户(User) → 角色(Role) → 权限(Permission)

关系说明:

一个用户可以有多个角色

一个角色可以有多个权限

权限决定可以访问哪些接口

第二部分:数据库设计

1.用户表

CREATE TABLE user (

id BIGINT PRIMARY KEY AUTO_INCREMENT,

username VARCHAR(50),

password VARCHAR(100)

);

2.角色表(role)

CREATE TABLE role (

id BIGINT PRIMARY KEY AUTO_INCREMENT,

role_name VARCHAR(50)

);

3.权限表(permission)

CREATE TABLE permission (

id BIGINT PRIMARY KEY AUTO_INCREMENT,

name VARCHAR(50),

path VARCHAR(100)

);

4.用户角色表(user_role)

CREATE TABLE user_role (

user_id BIGINT,

role_id BIGINT

);

5.角色权限表(role_permission)

CREATE TABLE role_permission (

role_id BIGINT,

permission_id BIGINT

);

6.示例数据

-- 用户

INSERT INTO user VALUES (1,'jack','123456');

INSERT INTO user VALUES (2,'lily','123456');

-- 角色

INSERT INTO role VALUES (1,'admin'),(2,'user');

-- 权限

INSERT INTO permission VALUES

(1,'查询商品','/goods/list'),

(2,'添加商品','/goods/add');

-- 用户角色

INSERT INTO user_role VALUES (1,1);

INSERT INTO user_role VALUES (2,2);

-- 角色权限

INSERT INTO role_permission VALUES (1,1),(1,2);

INSERT INTO role_permission VALUES (2,1);

第三部分:创建Mapper接口

  1. 创建UserMapper:
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    }

2.创建RoleMapper

@Mapper
public interface RoleMapper extends BaseMapper<Role> {
}

3.创建PermissionMapper

@Mapper
public interface PermissionMapper extends BaseMapper<Permission> {
}

4.创建UserRoleMapper

@Mapper
public interface PermissionMapper extends BaseMapper<Permission> {
}

5.创建RolePermissionMapper
@Mapper
public interface PermissionMapper extends BaseMapper<Permission> {
}

第四部分:创建DTO

  1. 创建MenuDTO

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MenuDTO {

private String name;

private String path;

private String permission;
}

  1. 创建UserInfoDTO

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfoDTO {

private Long userId;

private String username;

private List<String> roles;

private List<MenuDTO> menus;
}

第五部分:创建Service

1.创建PermissionService

@Service
public class PermissionService {

@Autowired
private UserRoleMapper userRoleMapper;

@Autowired
private RoleMapper roleMapper;

@Autowired
private RolePermissionMapper rolePermissionMapper;

@Autowired
private PermissionMapper permissionMapper;

public List<String> getUserRoles(Long userId) {
LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserRole::getUserId, userId);
List<UserRole> userRoles = userRoleMapper.selectList(wrapper);

List<Long> roleIds = userRoles.stream()
.map(UserRole::getRoleId)
.collect(Collectors.toList());

if (roleIds.isEmpty()) {
return new ArrayList<>();
}

List<Role> roles = roleMapper.selectBatchIds(roleIds);
return roles.stream()
.map(Role::getRoleName)
.collect(Collectors.toList());
}

public List<MenuDTO> getUserMenus(Long userId) {
List<String> roles = getUserRoles(userId);
if (roles.isEmpty()) {
return new ArrayList<>();
}

LambdaQueryWrapper<Role> roleWrapper = new LambdaQueryWrapper<>();
roleWrapper.in(Role::getRoleName, roles);
List<Role> roleList = roleMapper.selectList(roleWrapper);

List<Long> roleIds = roleList.stream()
.map(Role::getId)
.collect(Collectors.toList());

LambdaQueryWrapper<RolePermission> rpWrapper = new LambdaQueryWrapper<>();
rpWrapper.in(RolePermission::getRoleId, roleIds);
List<RolePermission> rolePermissions = rolePermissionMapper.selectList(rpWrapper);

List<Long> permissionIds = rolePermissions.stream()
.map(RolePermission::getPermissionId)
.distinct()
.collect(Collectors.toList());

if (permissionIds.isEmpty()) {
return new ArrayList<>();
}

List<Permission> permissions = permissionMapper.selectBatchIds(permissionIds);

return permissions.stream()
.map(p -> MenuDTO.builder()
.name(p.getName())
.path(p.getPath())
.permission(p.getName())
.build())
.collect(Collectors.toList());
}

public boolean hasPermission(Long userId, String permissionName) {
List<MenuDTO> menus = getUserMenus(userId);
return menus.stream()
.anyMatch(menu -> menu.getPermission().equals(permissionName));
}
}

2.创建RoleService

@Service
public class RoleService {

@Autowired
private RoleMapper roleMapper;

@Autowired
private UserRoleMapper userRoleMapper;

@Autowired
private RolePermissionMapper rolePermissionMapper;

public Long getRoleIdByName(String roleName) {
LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Role::getRoleName, roleName);
Role role = roleMapper.selectOne(wrapper);
return role != null ? role.getId() : null;
}

@Transactional
public void assignRoleToUser(Long userId, Long roleId) {
LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserRole::getUserId, userId);
userRoleMapper.delete(wrapper);

UserRole userRole = new UserRole();
userRole.setUserId(userId);
userRole.setRoleId(roleId);
userRoleMapper.insert(userRole);
}

@Transactional
public void assignPermissionToRole(Long roleId, Long permissionId) {
LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RolePermission::getRoleId, roleId)
.eq(RolePermission::getPermissionId, permissionId);

if (rolePermissionMapper.selectCount(wrapper) == 0) {
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(roleId);
rolePermission.setPermissionId(permissionId);
rolePermissionMapper.insert(rolePermission);
}
}
}

  1. 创建权限注解

第六部分:创建权限拦截器

  1. PermissionInterceptor

@Component
public class PermissionInterceptor implements HandlerInterceptor {

@Autowired
private JwtUtil jwtUtil;

@Autowired
private PermissionService permissionService;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) {
return true;
}

HandlerMethod handlerMethod = (HandlerMethod) handler;
RequirePermission requirePermission = handlerMethod.getMethodAnnotation(RequirePermission.class);

if (requirePermission == null) {
requirePermission = handlerMethod.getBeanType().getAnnotation(RequirePermission.class);
}

if (requirePermission != null) {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
}

Long userId = jwtUtil.getUserIdFromToken(token);
String permission = requirePermission.value();

if (!permissionService.hasPermission(userId, permission)) {
throw new BusinessException(403, "没有权限访问此资源");
}
}

return true;
}
}

  1. 注册该拦截器

registry.addInterceptor(permissionInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/auth/login", "/auth/register");

第七部分:创建权限管理 PermissionController

RestController
@RequestMapping("/permission")
public class PermissionController {

@Autowired
private PermissionService permissionService;

@Autowired
private RoleService roleService;

@Autowired
private JwtUtil jwtUtil;

@GetMapping("/menus")
public Result<List<MenuDTO>> getUserMenus(HttpServletRequest request) {
String token = (String) request.getAttribute("token");
Long userId = jwtUtil.getUserIdFromToken(token);

List<MenuDTO> menus = permissionService.getUserMenus(userId);
return Result.success(menus);
}

@GetMapping("/userinfo")
public Result<UserInfoDTO> getUserInfo(HttpServletRequest request) {
String token = (String) request.getAttribute("token");
Long userId = jwtUtil.getUserIdFromToken(token);
String username = jwtUtil.getUsernameFromToken(token);

List<String> roles = permissionService.getUserRoles(userId);
List<MenuDTO> menus = permissionService.getUserMenus(userId);

UserInfoDTO userInfo = UserInfoDTO.builder()
.userId(userId)
.username(username)
.roles(roles)
.menus(menus)
.build();

return Result.success(userInfo);
}

@PostMapping("/assign-role")
public Result<String> assignRole(@RequestParam Long userId, @RequestParam Long roleId) {
roleService.assignRoleToUser(userId, roleId);
return Result.success("角色分配成功");
}

@PostMapping("/assign-permission")
public Result<String> assignPermission(@RequestParam Long roleId, @RequestParam Long permissionId) {
roleService.assignPermissionToRole(roleId, permissionId);
return Result.success("权限分配成功");
}
}

第八部分:测试功能

1. 登录获取 token(使用你数据库中的用户)

POST http://localhost:8080/auth/login

{

"username": "你的用户名",

"password": "你的密码"

}

2. 获取动态菜单

GET http://localhost:8080/permission/menus

Authorization: Bearer {token}

3. 获取用户信息(含角色和权限)

GET http://localhost:8080/permission/userinfo

Authorization: Bearer {token}

4. 测试权限控制

GET http://localhost:8080/goods/list # 需要"查看商品"权限

POST http://localhost:8080/goods/add # 需要"商品管理"权限

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询