欢迎光临
我们一直在努力

已知菜单表,如何配置接口权限

— public.plat_menu definition — Drop table — DROP TABLE public.plat_menu; CREATE TABLE public.plat_menu ( id bigserial NOT NULL, menu_code varchar NULL, menu_name varchar NULL, list_order varchar NULL, created_by int8 DEFAULT 1 NULL, created_at timestamptz NULL, active bool DEFAULT true NULL, visible bool DEFAULT true NULL, subsys varchar DEFAULT 'opc'::character varying NULL, parent_id int8 DEFAULT '-1'::integer NULL, — 父节点 page_type int4 DEFAULT 10 NULL — 页面组件类型:10 菜单 20按扭 ); — Column comments COMMENT ON COLUMN public.plat_menu.parent_id IS '父节点'; COMMENT ON COLUMN public.plat_menu.page_type IS '页面组

基于您提供的 plat_menu 表结构,这是一个标准的树形菜单表(支持父子级联),但缺少与后端接口的映射关系。以下是完整的接口权限配置方案:

一、现有结构分析

当前表只解决了前端菜单展示问题:

  • page_type=10:导航菜单(侧边栏/顶部)

  • page_type=20:页面内按钮(增删改查按钮)

  • parent_id:构建树形结构

缺少的部分:菜单/按钮对应哪些后端API接口(如 POST /api/users)。

二、扩展方案:增加接口映射表

1. 创建接口定义表

sql

复制

— 存储所有需要权限控制的API
CREATE TABLE public.plat_api (
id bigserial PRIMARY KEY,
api_code varchar(100) NOT NULL UNIQUE, — 接口编码:user:add
api_name varchar(100) NOT NULL, — 接口名称:新增用户
api_url varchar(255) NOT NULL, — 请求路径:/api/users
http_method varchar(10) NOT NULL, — GET/POST/PUT/DELETE
description varchar(500),
created_at timestamptz DEFAULT NOW()
);

2. 创建菜单-接口关联表(多对多)

sql

复制

— 建立菜单/按钮与接口的多对多关系
CREATE TABLE public.plat_menu_api (
id bigserial PRIMARY KEY,
menu_id int8 NOT NULL REFERENCES plat_menu(id),
api_id int8 NOT NULL REFERENCES plat_api(id),
created_at timestamptz DEFAULT NOW(),
UNIQUE(menu_id, api_id)
);

3. 标准RBAC表结构(如未存在)

sql

复制

— 角色表
CREATE TABLE public.plat_role (
id bigserial PRIMARY KEY,
role_code varchar(50) NOT NULL UNIQUE,
role_name varchar(100) NOT NULL
);

— 角色-菜单关联(功能权限)
CREATE TABLE public.plat_role_menu (
id bigserial PRIMARY KEY,
role_id int8 NOT NULL REFERENCES plat_role(id),
menu_id int8 NOT NULL REFERENCES plat_menu(id),
UNIQUE(role_id, menu_id)
);

— 用户-角色关联
CREATE TABLE public.sys_user_role (
id bigserial PRIMARY KEY,
user_id int8 NOT NULL,
role_id int8 NOT NULL REFERENCES plat_role(id)
);

三、权限模型数据示例

场景:用户管理模块

sql

复制

— 1. 插入菜单结构
INSERT INTO plat_menu (menu_name, menu_code, page_type, parent_id) VALUES
('系统管理', 'sys:mgmt', 10, -1),
('用户管理', 'sys:user', 10, 1), — 假设系统管理id=1
('新增用户', 'sys:user:add', 20, 2), — 按钮
('删除用户', 'sys:user:del', 20, 2),
('编辑用户', 'sys:user:edit', 20, 2);

— 2. 注册接口
INSERT INTO plat_api (api_code, api_name, api_url, http_method) VALUES
('api:user:list', '查询用户列表', '/api/users', 'GET'),
('api:user:create', '新增用户', '/api/users', 'POST'),
('api:user:update', '更新用户', '/api/users/{id}', 'PUT'),
('api:user:delete', '删除用户', '/api/users/{id}', 'DELETE');

— 3. 建立映射(按钮级权限控制)
— "新增用户"按钮关联新增接口
INSERT INTO plat_menu_api (menu_id, api_id)
SELECT m.id, a.id
FROM plat_menu m, plat_api a
WHERE m.menu_code = 'sys:user:add' AND a.api_code = 'api:user:create';

— "用户管理"菜单关联查询接口(进入页面就需要查列表)
INSERT INTO plat_menu_api (menu_id, api_id)
SELECT m.id, a.id
FROM plat_menu m, plat_api a
WHERE m.menu_code = 'sys:user' AND a.api_code = 'api:user:list';

四、后端权限校验实现

Spring Boot 方案(注解+AOP)

java

复制

@Component
public class PermissionService {

@Autowired
private PlatMenuMapper menuMapper;

/**
* 判断当前用户是否有权限访问该接口
*/
public boolean hasPermission(Long userId, String requestUrl, String method) {
// 1. 根据URL和方法找到接口ID
Long apiId = menuMapper.findApiIdByUrl(requestUrl, method);
if (apiId == null) {
return true; // 未注册的接口默认放行(或根据策略拦截)
}

// 2. 查询用户拥有的所有菜单ID(通过角色)
List<Long> userMenuIds = menuMapper.findMenuIdsByUserId(userId);

// 3. 检查该接口是否被任何已授权菜单关联
Long count = menuMapper.checkApiInMenus(apiId, userMenuIds);
return count > 0;
}
}

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiresPermission {
// 可留空,自动根据URL匹配;或显式指定apiCode
String value() default "";
}

// 拦截器实现
@Component
public class PermissionInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取当前登录用户
Long userId = getCurrentUserId();
String url = request.getRequestURI();
String method = request.getMethod();

if (!permissionService.hasPermission(userId, url, method)) {
response.setStatus(403);
return false;
}
return true;
}
}

数据库查询示例

sql

复制

— 核心查询:用户是否有权限访问特定接口
SELECT COUNT(1)
FROM plat_role_menu rm
JOIN plat_menu_api ma ON rm.menu_id = ma.menu_id
JOIN plat_api api ON ma.api_id = api.id
WHERE rm.role_id IN (SELECT role_id FROM sys_user_role WHERE user_id = #{userId})
AND api.api_url = #{url}
AND api.http_method = #{method};

五、前端配合

动态路由 + 按钮级权限:

JavaScript

复制

// 1. 登录后获取用户权限树(包含menus和apis)
const userPermissions = await getUserPermissions();

// 2. 前端按钮显示控制(v-if)
<button v-if="hasPermission('sys:user:add')">新增用户</button>

// 3. API请求拦截(双重保险)
// 虽然后端会拦,但前端可提前预判,提升体验

六、进阶方案

表格

复制

方案适用场景特点
菜单-接口绑定(上述方案) 标准RBAC 配置清晰,颗粒度到按钮
数据权限 部门隔离 增加 data_scope 字段(全部/本部门/本人)
接口注解 快速开发 不用维护plat_api表,直接注解 @RequireRole("admin")
动态权限 复杂业务 使用Apache Shiro或Spring Security,支持运行时变更

数据权限扩展

如需控制"只能看本部门数据":

sql

复制

— 角色表增加数据权限范围
ALTER TABLE plat_role ADD COLUMN data_scope int DEFAULT 1;
— 1:全部 2:本部门 3:本部门及下级 4:仅本人

— 用户表增加部门字段
ALTER TABLE sys_user ADD COLUMN dept_id int8;

核心逻辑:查询数据时自动拼接 WHERE dept_id IN (用户可见部门)。

这套方案实现了前端菜单可见性与后端接口访问控制的统一,通过 plat_menu_api 关联表解耦,既支持粗粒度(菜单级)也支持细粒度(按钮级)权限控制。

件类型:10 菜单 20按扭'; 已知菜单表,如何配置接口权限

赞(0)
未经允许不得转载:171主机测评 » 已知菜单表,如何配置接口权限
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址