Spring Boot 多角色权限隔离实战:接口层+路由层+UI层三层防御,杜绝生产数据泄露

做过企业系统的开发者几乎都踩过这个坑:本地测试一切正常,上线后发现 A 角色的用户能看到本不该看到的 B 角色数据。

为什么会这样?因为权限控制被做成了"单层防御"------要么只在前端判断,要么只在某一个接口里过滤,整个链路上只有一道门,一旦那道门没关好,数据就泄出去了。

以一个真实场景为例:系统里有"机构用户"和"学校用户"两种角色,学校专属的周程视图、校历数据,机构用户本来不该看到,但接口层没过滤、路由层没拦截、UI 层也没控制功能入口,三层全漏。

多角色权限隔离:三层防御体系

第一层:接口层数据过滤(后端必做)

按角色在接口返回前就过滤掉对方不该看的数据。让前端判断"该不该展示"是最常见的错误------前端代码可以被绕过,而且容易被遗漏。

java 复制代码
// 推荐:接口层根据角色类型过滤可选日历
public List<CalendarVO> getAvailableCalendars(UserContext ctx) {
    List<CalendarVO> all = calendarRepo.findAll();
    if (ctx.isInstitutionUser()) {
        // 机构用户只看通用日历,过滤掉学校专属类型
        return all.stream()
            .filter(c -> !SCHOOL_ONLY_TYPES.contains(c.getType()))
            .collect(Collectors.toList());
    }
    return all;
}

第二层:路由权限用白名单(前端必做)

给每种角色定义允许访问的路由白名单,在路由守卫里统一拦截,业务页面不做二次判断。黑名单思路总会漏,新加一个路由就得记得去黑名单加一条,迟早出问题。

javascript 复制代码
// 路由白名单配置
const ROLE_ROUTE_WHITELIST = {
  institution: ['/home', '/calendar/department', '/schedule'],
  school: ['/home', '/calendar/school', '/schedule', '/semester'],
}

// 路由守卫统一拦截
router.beforeEach((to, from, next) => {
  const userRole = store.getters.userRole
  const allowedRoutes = ROLE_ROUTE_WHITELIST[userRole] || []
  if (!allowedRoutes.includes(to.path)) {
    next('/home')
  } else {
    next()
  }
})

第三层:功能入口按角色控制(UI 层必做)

不只是数据,UI 上的切换按钮、菜单入口也要按角色控制显隐。把角色判断逻辑抽到配置层,避免 v-if 散落在每个组件里。

javascript 复制代码
// 功能可见性配置
const FEATURE_VISIBILITY = {
  semesterSwitcher: ['school'],    // 学期视图切换:仅学校用户
  schoolCalendar:   ['school'],    // 学校专属日历:仅学校用户
  departmentCalendar: ['school', 'institution'],  // 部门日历:两类用户都可见
}

// 在 store 里统一判断
getters: {
  canSeeFeature: (state) => (feature) => {
    return FEATURE_VISIBILITY[feature]?.includes(state.userRole) ?? false
  }
}

容易被忽略的两个细节

可选字段 null 时不渲染,而不是显示"无xxx"

javascript 复制代码
// 错误:展示"无提醒"让用户困惑
<div>提醒:{{ alarm || '无提醒' }}</div>

// 正确:null 就不渲染这一行
<div v-if="alarm !== null">提醒:{{ alarm }}</div>

空状态必须有缺省页

列表为空时给个引导图,用户不会以为系统出了问题。这是体验完整性的最后一公里。

在 AI 多租户场景同样适用

这五个设计点在 AI 应用的多租户场景里一模一样:A 公司的知识库数据绝不能出现在 B 公司的 RAG 检索结果里,tenant_id 过滤要在向量检索的 filter 条件里做,不能依赖上层业务逻辑判断。

权限隔离是系统可信赖的基础,不是可选项。

更多 Java 转 AI 实战内容,持续更新在「Java 转 AI 实战内参」星球。

相关推荐
马剑威(威哥爱编程)3 分钟前
【AI全栈后端12-12】Spring Boot 3.x 到 4.x 迁移实操:Jakarta 11、Jackson 3 与 AI 2.0
java·开发语言·spring boot·后端
IT研究室11 分钟前
最新计算机毕业设计选题推荐-基于spring boot的心桥·心理健康综合服务平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
星恒随风25 分钟前
Linux基础IO万字详解:从文件描述符fd到重定向、FILE缓冲机制及MiniShell升级
linux·运维·笔记·学习·状态模式
她的男孩39 分钟前
企业接口照样拦得住:独立 Flyway、@RequiresFeature 与离线许可证
java·spring boot·后端
十年Java程序媛39 分钟前
Lambda 与函数式接口|别只会复制 ()->{},底层规则和坑一次性讲清
java·spring boot·后端
马剑威(威哥爱编程)2 小时前
【AI全栈后端12-11】Spring Boot 把 AI 接口真正上线扛量:限流 / 降级 / 可观测
人工智能·spring boot·后端
RuoyiOffice2 小时前
SpringBoot+Vue3+Onlyoffice 企业文件生命周期:上传、业务关联、权限、版本与安全清理
spring boot·vue3·文件管理·对象存储·权限控制·ruoyi office·附件管理
阿狗童鞋3 小时前
高并发系统设计实战指南
java·spring boot·spring cloud
十年Java程序媛17 小时前
Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型
java·spring boot·后端
for_ever_love__19 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结