FastBee 安全公告与漏洞修复
官方维护代码已包含相应修复;首个包含各项修复的正式发布版本仍需逐项核验。以下状态区分维护代码、修复提交和正式发布版本,不能用“更新最新代码”替代实例检查。
修复状态速览
| 项目 | 受影响范围或性质 | 官方修复状态 | 升级与验证 |
|---|---|---|---|
| 默认口令部署风险 | 初始部署凭据,公网暴露后风险 | 部署流程保持不变,由用户部署后修改 | 公网或生产环境部署后修改默认口令并验证强度 |
| 演示账号逻辑缺陷 | 演示角色缓存权限与数据权限 | 维护代码已修复;首个正式发布版本待核验 | 检查 monitor:cache:list 和游客角色数据权限 |
| go-view 任意 SQL 执行 | 未授权 SQL 直连接口 | 维护代码已修复;首个正式发布版本待核验 | 不需要时禁用;需要时鉴权,并验证匿名请求被拒绝 |
| 存储型 XSS | 新闻、公告和设备日志渲染与入库 | 维护代码已修复;首个正式发布版本待核验 | 验证恶意标记被净化且正常富文本可用 |
| CVE-2025-15251(XXE) | FastBee 2.1 及以前(NVD) | 维护代码已修复;首个正式发布版本待核验 | 禁止 DTD/外部实体,并限制 SIP 网络暴露 |
| CVE-2026-7676(任意文件读取) | FastBee 1.2.1 及以前(NVD) | 维护代码已修复;首个正式发布版本待核验 | 验证目录外不可读且正常下载不受影响 |
| CVE-2026-111654(设备组 IDOR) | FastBee 2.1.0 及以前(CVE) | 维护代码已修复;首个正式发布版本待核验 | 用两个不同所有者账号验证五类设备组操作 |
| CVE-2026-120274(Groovy RCE) | FastBee 2.1.0 及以前(NVD/AVD) | 维护代码已修复;修复提交;首个正式发布版本待核验 | 验证编译期和运行期防护,以及入库/热加载前校验 |
| 垂直越权 | 低权限账号访问管理员接口 | 维护代码已修复;首个正式发布版本待核验 | 按权限矩阵验证 403 和数据范围,不能只隐藏菜单 |
默认账号密码用于首次部署,用户可在部署后自行修改;提供初始凭据本身不改变现有部署流程。公网或生产环境仍应在上线前修改默认口令、限制演示账号权限,避免被扫描器直接利用。
完整的上线检查见部署前安全核验清单,修复版本、二开升级和实例验证问题见安全常见问题。
安全公告
- 本页汇总 FastBee 已公开安全问题、维护代码修复状态和实例验收指引,请结合实际部署尽快完成升级与验证。
- 首个正式发布版本待核验的条目,不得仅凭版本号推断实例已经安全;应同时核对部署代码、配置、权限和回归结果。
- 修复前请备份程序、配置与数据,并先在测试环境验证业务兼容性。
报告安全问题
请发送邮件至 164770707@qq.com,标题注明「FastBee 安全问题」,并附上使用版本、受影响产品、复现步骤、影响说明及相关日志。对尚未公开的问题,请勿先在公开 Issue 中披露漏洞细节或可利用的 POC。
1. 弱指令漏洞修复
漏洞说明:平台admin管理员密码、数据库密码、redis密码、emq控制台密码等过于简单,可能导致攻击者未授权访问系统,从而数据泄露、纂改或其他恶意活动,对用户和企业造成严重影响。
修复建议:更改以上密码,设置复杂高强度密码,定期更换密码,加强服务器防护。
2. 逻辑缺陷漏洞修复
漏洞说明:平台存在演示账号,并且明文说明账号密码是 fastbee 123456。如果该账号角色分配了缓存监控或缓存列表monitor:cache:list权限,则可通过缓存获取其他用户登录信息,并使用该用户信息登录到平台,对安全造成极大隐患。
修复建议:对演示账号的角色不分配该权限。
3. SQL 注入漏洞修复
漏洞说明:go-view数据可视化大屏功能集成了一个SQL直连执行能力,无需登录或任何凭证可输入任意查询SQL执行。代码位置:com.fastbee.controller.goview.GoviewProjectDataController
修复建议:
1、如果不需要该功能,直接注释或删除该文件;
2、如果需要该功能,则需要为该接口com.fastbee.controller.goview.GoviewProjectDataController#executeSql添加登录权限校验;
4. XSS 漏洞修复
漏洞说明:
1、新闻和通知公告内容使用Vue的v-html指令直接渲染到DOM中,未进行任何HTML转义或净化处理。修复建议:前后端加XSS过滤;
2、设备上报的日志数据(logValue)未经过任何HTML过滤或转义处理,直接存储到数据库,前端使用v-html指令直接渲染logValue,导致恶意脚本在管理员浏览器中执行。修复建议:前端渲染加XSS过滤;
4.1. 开源版本修复
开源版可直接更新最新代码
4.2. 商业版本修复
4.2.1. 前端修复
以下是针对最新版本的修复,用户更新未过期的可以直接更新代码,如果代码更新过期的可使用以下步骤修复,如果使用的是vue2版本的用户,可以参考以下内容自行修复
- vue3/package.json 文件"dependencies" 里面加入
"dompurify": "^3.4.13",新增文件: 在vue3/src/directive/module/下新增一个safeHtml.ts文件
新增文件: 在vue3/src/utils下新增一个文件名为"security.ts"的文件
替换vue3/src/utils/index.js 文件
替换vue3/src/components/Editor/index.vue 文件
替换vue3/src/utils/map.js 文件
以下文件将"v-html",替换成”v-safe-html.presentation”
- src/views/iot/device/device-log.vue,
- src/views/iot/alert/log.vue,
- src/views/iot/clientDetails/index.vue,
- src/views/iot/device/device-alert.vue,
- src/views/iot/device/device-timer.vue,
- src/views/iot/product/product-things-model.vue,
- src/views/iot/scene/log.vue,
- src/views/iot/simulate/index.vue,
- src/views/visualBigScreen/management/packages/components/Tables/Tables/TableList/index.vue,
- src/views/visualBigScreen/management/packages/components/Tables/Tables/TableScrollBoard/index.vue,替换src/views/system/notice/index.vue
替换src/views/ruleegine/editor/js/jsplumb.js
替换src/views/iot/news/index.vue文件
4.2.2. 后端修复
- springboot/fastbee-common-extend/pom.xml 文件,引入包
<!-- 富文本白名单净化 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.18.3</version>
</dependency>- springboot/fastbee-service/fastbee-system-service/pom.xml 文件,引入包
<!-- 单元测试组件 -->
<dependency>
<groupId>com.fastbee</groupId>
<artifactId>fastbee-test</artifactId>
<scope>test</scope>
</dependency>- springboot\fastbee-service\fastbee-iot-service\src...\iot\service\impl\NewsServiceImpl#insertNews 方法
/**
* 新增新闻资讯
*
* @param news 新闻资讯
* @return 结果
*/
@Override
public int insertNews(News news)
{
sanitizeNews(news);
news.setCreateTime(DateUtils.getNowDate());
news.setCreateBy(getUserName());
return newsMapper.insert(news);
}- springboot\fastbee-service\fastbee-iot-service\src...\iot\service\impl\NewsServiceImpl#updateNews 方法
/**
* 修改新闻资讯
*
* @param news 新闻资讯
* @return 结果
*/
@Override
public int updateNews(News news)
{
sanitizeNews(news);
news.setUpdateTime(DateUtils.getNowDate());
news.setUpdateBy(getUserName());
return newsMapper.updateById(news);
}- springboot\fastbee-service\fastbee-iot-service\src...\iot\service\impl\NewsServiceImpl#新增sanitizeNews 方法
private void sanitizeNews(News news)
{
news.setTitle(RichTextSanitizer.sanitizePlainText(news.getTitle()));
news.setContent(RichTextSanitizer.sanitizeRichText(news.getContent()));
news.setImgUrl(RichTextSanitizer.sanitizePlainText(news.getImgUrl()));
news.setCategoryName(RichTextSanitizer.sanitizePlainText(news.getCategoryName()));
news.setAuthor(RichTextSanitizer.sanitizePlainText(news.getAuthor()));
news.setRemark(RichTextSanitizer.sanitizePlainText(news.getRemark()));
}- springboot\fastbee-service\fastbee-iot-service...\iot\service\NewsServiceImplTest.java 类,新增以下两个方法
@Test
@DisplayName("insertNews - 应净化新闻纯文本和富文本中的 XSS")
void testInsertNews_ShouldSanitizeXss() {
News news = new News();
news.setTitle("<b>新闻标题</b><script>alert(1)</script>");
news.setContent("<p class=\"ql-align-center\">正文</p><img src=\"/test.jpg\" onerror=\"alert('XSS')\"><script>alert(2)</script>");
news.setAuthor("<img src=x onerror=alert(3)>管理员");
when(newsMapper.insert(any(News.class))).thenReturn(1);
assertEquals(1, newsService.insertNews(news));
assertEquals("新闻标题", news.getTitle());
assertEquals("管理员", news.getAuthor());
assertTrue(news.getContent().contains("<p class=\"ql-align-center\">正文</p>"));
assertTrue(news.getContent().contains("<img src=\"/test.jpg\">"));
assertFalse(news.getContent().contains("onerror"));
assertFalse(news.getContent().contains("<script"));
}
@Test
@DisplayName("updateNews - 应移除危险链接协议并保留安全链接")
void testUpdateNews_ShouldSanitizeDangerousProtocol() {
News news = new News();
news.setNewsId(randomLongId());
news.setContent("<a href=\"javascript:alert(1)\">危险链接</a><a href=\"https://fastbee.cn\" target=\"\_blank\">安全链接</a>");
when(newsMapper.updateById(any(News.class))).thenReturn(1);
assertEquals(1, newsService.updateNews(news));
assertFalse(news.getContent().contains("javascript:"));
assertTrue(news.getContent().contains("href=\"https://fastbee.cn\""));
assertTrue(news.getContent().contains("rel=\"nofollow noopener noreferrer\""));
}- springboot\fastbee-service\fastbee-system-service...\service\impl\SysNoticeServiceImpl.java类,修改insertNotice、updateNotice方法,新增sanitizeNotice方法
/\*\*
_ 新增公告
_
_ @param notice 公告信息
_ @return 结果
\*/
@Override
public int insertNotice(SysNotice notice)
{
sanitizeNotice(notice);
return noticeMapper.insert(notice);
}
/**
* 修改公告
*
* @param notice 公告信息
* @return 结果
*/
@Override
public int updateNotice(SysNotice notice)
{
sanitizeNotice(notice);
notice.setUpdateTime(DateUtils.getNowDate());
return noticeMapper.updateById(notice);
}
private void sanitizeNotice(SysNotice notice)
{
notice.setNoticeTitle(RichTextSanitizer.sanitizePlainText(notice.getNoticeTitle()));
notice.setNoticeContent(RichTextSanitizer.sanitizeRichText(notice.getNoticeContent()));
notice.setRemark(RichTextSanitizer.sanitizePlainText(notice.getRemark()));
}- springboot\fastbee-common-extend\src\main\java\com\fastbee\common\extend\utils\html\新增RichTextSanitizer.java类
package com.fastbee.common.extend.utils.html;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Cleaner;
import org.jsoup.safety.Safelist;
/\*\*
- 用户可编辑富文本的 XSS 白名单净化工具。
\*/
public final class RichTextSanitizer {
private static final Safelist RICH_TEXT_SAFELIST = Safelist.relaxed()
.addTags("figure", "figcaption", "hr")
.addAttributes(":all", "class", "title")
.addAttributes("a", "target", "rel")
.addAttributes("img", "loading")
.addAttributes("table", "border", "cellpadding", "cellspacing")
.addAttributes("td", "colspan", "rowspan")
.addAttributes("th", "colspan", "rowspan", "scope")
.addProtocols("a", "href", "http", "https", "mailto")
.addProtocols("img", "src", "http", "https")
.addEnforcedAttribute("a", "rel", "nofollow noopener noreferrer")
.preserveRelativeLinks(true);
private RichTextSanitizer() {
}
/**
* 保留安全的排版标签,移除脚本、事件属性和危险协议。
*
* @param html 待净化的富文本
* @return 可安全交给前端 HTML 渲染的内容
*/
public static String sanitizeRichText(String html) {
if (html == null) {
return null;
}
Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
Document document = Jsoup.parseBodyFragment(html, "https://fastbee.invalid");
Document cleanDocument = new Cleaner(RICH_TEXT_SAFELIST).clean(document);
cleanDocument.outputSettings(outputSettings);
// 协议相对地址会随页面协议指向任意外部站点,富文本中不允许使用。
for (Element element : cleanDocument.select("[href], [src]")) {
for (String attribute : new String[]{"href", "src"}) {
if (element.hasAttr(attribute) && element.attr(attribute).trim().startsWith("//")) {
element.removeAttr(attribute);
}
}
}
return cleanDocument.body().html();
}
/**
* 移除纯文本字段中的全部 HTML 标签及可执行内容。
*
* @param text 待净化的文本
* @return 不包含 HTML 标签的文本
*/
public static String sanitizePlainText(String text) {
if (text == null) {
return null;
}
Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
return Jsoup.clean(text, "", Safelist.none(), outputSettings);
}
}- springboot\fastbee-service\fastbee-system-service\src\test\java\com\fastbee\system\service\新增SysNoticeServiceImplTest.java类
package com.fastbee.system.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import com.fastbee.framework.core.ut.BaseMockitoUnitTest;
import com.fastbee.system.domain.SysNotice;
import com.fastbee.system.mapper.SysNoticeMapper;
import com.fastbee.system.service.impl.SysNoticeServiceImpl;
/\*\*
- {@link SysNoticeServiceImpl} 单元测试。
\*/
@DisplayName("通知公告 Service 单元测试")
@Tag("dev")
class SysNoticeServiceImplTest extends BaseMockitoUnitTest {
@InjectMocks
private SysNoticeServiceImpl noticeService;
@Mock
private SysNoticeMapper noticeMapper;
@Test
@DisplayName("insertNotice - 应净化标题和公告富文本中的 XSS")
void insertNoticeShouldSanitizeXss() {
SysNotice notice = new SysNotice();
notice.setNoticeTitle("<b>安全公告</b><script>alert(1)</script>");
notice.setNoticeContent("<p>公告正文</p><img src=\"/test.jpg\" onerror=alert('XSS')><iframe src=\"https://example.com\"></iframe>");
when(noticeMapper.insert(any(SysNotice.class))).thenReturn(1);
assertEquals(1, noticeService.insertNotice(notice));
assertEquals("安全公告", notice.getNoticeTitle());
assertTrue(notice.getNoticeContent().contains("<p>公告正文</p>"));
assertTrue(notice.getNoticeContent().contains("<img src=\"/test.jpg\">"));
assertFalse(notice.getNoticeContent().contains("onerror"));
assertFalse(notice.getNoticeContent().contains("iframe"));
verify(noticeMapper).insert(notice);
}
@Test
@DisplayName("updateNotice - 应在修改前净化 XSS 并设置更新时间")
void updateNoticeShouldSanitizeXssAndSetUpdateTime() {
SysNotice notice = new SysNotice();
notice.setNoticeId(1L);
notice.setNoticeContent("<a href=\"javascript:alert(1)\">链接</a><strong>正常内容</strong>");
when(noticeMapper.updateById(any(SysNotice.class))).thenReturn(1);
assertEquals(1, noticeService.updateNotice(notice));
assertFalse(notice.getNoticeContent().contains("javascript:"));
assertTrue(notice.getNoticeContent().contains("<strong>正常内容</strong>"));
assertNotNull(notice.getUpdateTime());
verify(noticeMapper).updateById(notice);
}
}5. SIP XML 外部实体(XXE):CVE-2025-15251
受影响版本: NVD 记录为 FastBee 2.1 及以前版本。问题位于 SIP Message Handler 的 ReqAbstractHandler.getRootElement,恶意 XML 外部实体引用可能导致服务器敏感文件被读取。利用需要 SIP 服务网络可达,并满足有效 deviceSipId 等条件;不能把它理解为所有部署都可被无条件远程利用。
处置建议:
- 不使用视频 SIP 接入时,关闭并限制 SIP 服务端口,避免将 5060/5061 直接暴露到不可信网络;删除演示设备和默认凭据。
- 核验实际代码中的 XML 解析器是否禁止 DTD、外部通用实体和外部参数实体。仅升级 JDK 不能替代解析器安全配置。
- 仍在受影响代码上的部署,应在测试环境验证后升级到受维护版本,并检查
ReqAbstractHandler的真实差异;本页不根据 CVE 影响范围反推未经证实的修复版本。 - 修复后使用不含真实敏感信息的测试数据验证外部 DTD 和实体请求被拒绝,同时检查 SIP 日志与出站连接。
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);参考:NVD CVE-2025-15251、FastBee 官方仓库 Issue ID7HNZ。
6. 下载接口任意文件读取:CVE-2026-7676
受影响版本: NVD 记录为 FastBee 1.2.1 及以前版本。问题位于 springboot/fastbee-open-api/src/main/java/com/fastbee/data/controller/ToolController.java 的 ToolController.download,fileName 参数路径遍历可能读取预期下载目录之外的文件,构成任意文件读取风险。
处置建议:
- 仍使用受影响版本的部署,应核验该接口和参数处理代码,在测试环境验证后升级到受维护版本;不要仅凭版本号或第三方复现文章判断当前实例状态。
- 下载逻辑应使用规范化后的绝对路径,并确认目标仍位于允许的下载目录内;拒绝绝对路径、目录穿越和符号链接逃逸,不能只做字符串替换。
- 对下载接口实施身份认证、权限校验和访问日志;不需要该接口时,应在网关和应用层同时禁用。
- 修复后使用隔离的测试目录验证目录外文件不可读,且正常下载功能不受影响。
7. 设备组越权访问(IDOR):CVE-2026-111654
受影响版本: CVE 记录为 FastBee 2.1.0 及以前版本。GroupController 相关查询缺少设备组所有者校验时,已认证的低权限用户可能通过组 ID 读取、覆盖、重新分配、修改设备关联或删除其他用户的设备组。
处置建议:
- 在控制器、服务和 Mapper 查询链路中同时核验设备组所有者或租户边界,不能只隐藏前端按钮,也不能仅校验组 ID 是否存在。
- 对读取、更新、重新分配、设备关联变更和删除操作执行一致的设备组所有者校验,并记录越权拒绝与异常变更日志。
- 不需要公开注册时关闭自助注册;检查现有低权限账号、演示账号和设备组数据是否出现跨用户异常。
- 使用两个不同所有者的测试账号验证所有设备组读写路径均返回正确的授权结果,再核对实际代码差异和回归测试。
版本核验边界
上述受影响版本来自公开 CVE 记录,用于确定排查范围,不代表本页已经确认某个后续版本包含完整修复。实际处置应同时核对部署版本、相关源码、修复提交和回归测试;未核实的修复版本或提交不在本页宣称。
8. 规则脚本 Groovy 注入导致 RCE:CVE-2026-120274
受影响版本: NVD 与阿里云漏洞库记录为 FastBee 2.1.0 及以前版本。/iot/script 的新增、编辑链路如果只删除 import 语句就把脚本热加载到默认 Groovy 执行器,缺少沙箱和危险类隔离时,具备脚本编辑权限的远程攻击者可能在服务端执行任意代码。设备上报或平台下发会触发已加载脚本。
该问题要求攻击者已经具备脚本编辑权限,不是匿名无权限利用。因此,垂直越权修复、脚本编辑权限收紧和 Groovy 执行器防护必须同时验收。
官方修复: 维护代码已包含修复,公开修复提交为 890a33846005a937a58cccd738b7fb9821b82ea9;首个正式发布版本待核验。
修复实现通过 SecureGroovyScriptExecutor.compileSource 与 BusinessScriptInterceptor 切断危险链路:
- 编译期: 拒绝类声明、包声明、注解和自定义构造器,避免通过脚本定义新的可执行结构。
- 运行期: 默认拒绝进程、文件和反射调用,不能依赖删除
import或隐藏脚本编辑入口代替防护。 - 入库与热加载前: 新增和编辑脚本必须先通过同一编译器校验,不能只在校验后保存,却在热加载时绕过编译约束。
- 权限与审计: 仅向确有需要的角色开放脚本编辑权限,并记录脚本变更和异常执行日志。
回归验收:
- 在隔离测试环境分别验证类/包/注解/自定义构造器被拒绝,以及进程、文件和反射调用被拒绝。
- 验证新增和编辑链路在入库前、热加载前执行同一套校验,合法业务脚本仍能按预期运行。
- 使用普通权限账号确认无法取得脚本编辑能力,并检查历史脚本和运行日志是否已有异常变更。
参考:NVD CVE-2026-120274、阿里云 AVD-2026-120274。
9. 垂直越权漏洞修复
攻击者可利用该漏洞通过低权限账户处置越权访问只有管理员才能使用的系统接口,对应需要增加权限校验。对应接口如下:
- /system/user/2
- /system/user/authRole/1
- /system/config/list?pageNum=1&pageSize=10
- /system/role/list?pageNum=1&pageSize=10
- /system/post/list?pageNum=1&pageSize=10
- /system/dept/100
- /system/user/list?pageNum=1&pageSize=10
9.1. 开源版本修复
- springboot/fastbee-admin/src/main/java/com/fastbee/web/controller/system/SysDeptController.java文件
/**
* 根据部门编号获取详细信息
*/
@ApiOperation("根据部门编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
List<String> currentRoleKeys = loginUser.getUser().getRoles().stream()
.map(role -> role.getRoleKey())
.collect(Collectors.toList());
if (currentRoleKeys.contains("visitor")) {
return AjaxResult.error(403, "游客无权限访问部门信息!");
}
try {
deptService.checkDeptDataScope(deptId);
} catch (ServiceException e) {
return AjaxResult.error(403, e.getMessage());
}
SysDept dept = deptService.selectDeptById(deptId);
return AjaxResult.success(dept);
}9.1.1. 后端修复
- springboot/fastbee-admin/src/main/java/com/fastbee/web/controller/system/SysUserController.java文件
/\*\*
_ 根据用户编号获取详细信息
_/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{
AjaxResult ajax = AjaxResult.success();
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser currentUser = loginUser.getUser();
Long currentUserId = currentUser.getUserId();
List<String> currentRoleKeys = currentUser.getRoles().stream()
.map(SysRole::getRoleKey)
.collect(Collectors.toList());
if (currentRoleKeys.contains("visitor")) {
return AjaxResult.error(403, "游客无权限访问用户信息!");
}
if (StringUtils.isNotNull(userId))
{
try {
userService.checkUserDataScope(userId);
} catch (ServiceException e) {
return AjaxResult.error(403, e.getMessage());
}
SysUser sysUser = userService.selectUserById(userId);
// 非超管过滤超管角色信息
if (!SysUser.isAdmin(currentUserId)) {
List<SysRole> filterRoles = sysUser.getRoles().stream()
.filter(r -> !r.isAdmin())
.collect(Collectors.toList());
sysUser.setRoles(filterRoles);
}
// 封装数据
ajax.put(AjaxResult.DATA_TAG, sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId));
List<Long> roleIds = sysUser.getRoles().stream()
.map(SysRole::getRoleId)
.collect(Collectors.toList());
ajax.put("roleIds", roleIds);
}
// 角色/岗位列表过滤
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(currentUserId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
// ========== 8. 岗位列表:仅用selectPostListByUserId(适配现有方法) ==========
if (SysUser.isAdmin(currentUserId)) {
// 超管:返回所有岗位
ajax.put("posts", postService.selectPostAll());
} else {
// 非超管:仅返回当前登录用户自己的岗位
ajax.put("posts", postService.selectPostListByUserId(currentUserId));
}
return ajax;
}
/**
* 根据用户编号获取授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
AjaxResult ajax = AjaxResult.success();
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser currentUser = loginUser.getUser();
Long currentUserId = currentUser.getUserId();
List<String> currentRoleKeys = currentUser.getRoles().stream()
.map(SysRole::getRoleKey)
.collect(Collectors.toList());
if (currentRoleKeys.contains("visitor")) {
return AjaxResult.error(403, "游客无权限访问用户授权角色信息!");
}
try {
userService.checkUserDataScope(userId);
} catch (ServiceException e) {
return AjaxResult.error(403, e.getMessage());
}
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
List<SysRole> filterRoles = SysUser.isAdmin(currentUserId)
? roles // 超管返回所有授权角色
: roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()); // 非超管过滤超管角色
ajax.put("user", user);
ajax.put("roles", filterRoles);
return ajax;
}- springboot/fastbee-service/fastbee-system-service/src/main/java/com/fastbee/system/service/impl/SysDeptServiceImpl.java 文件
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
@Override
public void checkDeptDataScope(Long deptId)
{
if (SysUser.isAdmin(SecurityUtils.getUserId())) {
return;
}
SysDept queryDept = new SysDept();
List<SysDept> accessibleDepts = SpringUtils.getAopProxy(this).selectDeptList(queryDept);
if (CollectionUtils.isEmpty(accessibleDepts)) {
throw new ServiceException("没有权限访问部门数据!");
}
boolean hasPermission = accessibleDepts.stream()
.anyMatch(dept -> dept.getDeptId().equals(deptId));
if (!hasPermission) {
throw new ServiceException("没有权限访问该部门数据!");
}
SysDept targetDept = this.selectDeptById(deptId);
if (targetDept == null) {
throw new ServiceException("部门不存在!");
}
}- springboot/fastbee-service/fastbee-system-service/src/main/java/com/fastbee/system/service/impl/SysPostServiceImpl.java 文件
/**
* 查询岗位信息集合
*
* @param post 岗位信息
* @return 岗位信息集合
*/
@Override
public List<SysPost> selectPostList(SysPost post)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser.getUser().getRoles().stream()
.map(role -> role.getRoleKey())
.collect(Collectors.toList()).contains("visitor")) {
return Collections.emptyList();
}
List<SysPost> postList = postMapper.selectPostList(post);
return CollectionUtils.isEmpty(postList) ? Collections.emptyList() : postList;
}- springboot/fastbee-service/fastbee-system-service/src/main/java/com/fastbee/system/service/impl/SysRoleServiceImpl.java 文件
/\*\*
_ 根据条件分页查询角色数据
_
_ @param role 角色信息
_ @return 角色数据集合信息
\*/
@Override
@DataScope(deptAlias = "d")
public List<SysRole> selectRoleList(SysRole role)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
List<String> currentRoleKeys = loginUser.getUser().getRoles().stream()
.map(SysRole::getRoleKey)
.collect(Collectors.toList());
if (currentRoleKeys.contains("visitor")) {
return Collections.emptyList();
}
List<SysRole> roleList = roleMapper.selectRoleList(role);
if (CollectionUtils.isEmpty(roleList)) {
return Collections.emptyList();
}
Long currentUserId = loginUser.getUser().getUserId();
if (SysUser.isAdmin(currentUserId)) {
return roleList;
} else {
return roleList.stream()
.filter(r -> !r.isAdmin())
.collect(Collectors.toList());
}
}- src/views/index.vue 文件下的“v-html”替换成“v-safe-html”,然后引入
import { escapeHtml } from '@/utils/security';- script加入以下方法代码
function appendInfoLine(container: HTMLElement, label: string, value: unknown, highlight = false) {
container.append(document.createTextNode(`${label}:`));
const text = String(value ?? '');
if (highlight) {
const span = document.createElement('span');
span.style.color = '#486FF2';
span.textContent = text;
container.appendChild(span);
} else {
container.append(document.createTextNode(text));
}
container.appendChild(document.createElement('br'));
}
function appendColoredInfoLine(container: HTMLElement, label: string, value: unknown, color: string) {
container.append(document.createTextNode(`${label}:`));
const span = document.createElement('span');
span.style.color = color;
span.textContent = String(value ?? '');
container.appendChild(span);
container.appendChild(document.createElement('br'));
}src/views/ai/chat/index.vue 文件下的“v-html”替换成 “v-safe-html.markdown”
springboot/fastbee-service/fastbee-system-service/src/main/java/com/fastbee/system/service/impl/SysUserServiceImpl.java 文件
/**
* 根据条件分页查询用户列表
*
* @param user 用户信息
* @return 用户信息集合信息
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUserList(SysUser user)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser currentUser = loginUser.getUser();
Long currentUserId = currentUser.getUserId();
Long currentDeptId = currentUser.getDeptId();
if (!SecurityUtils.isAdmin(currentUserId)) {
user.setDeptId(currentDeptId);
user.setUserId(currentUserId);
return userMapper.selectUserList(user);
}
return userMapper.selectUserList(user);
}
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
@Override
public void checkUserDataScope(Long userId)
{
Long currentUserId = SecurityUtils.getUserId();
// 超管直接放行
if (SysUser.isAdmin(currentUserId)) {
return;
}
SysUser queryCondition = new SysUser();
List<SysUser> accessibleUsers = SpringUtils.getAopProxy(this).selectUserList(queryCondition);
boolean hasPermission = accessibleUsers.stream()
.anyMatch(u -> u.getUserId().equals(userId));
SysUser targetUser = this.selectUserById(userId);
if (targetUser != null && SysUser.isAdmin(targetUser.getUserId())) {
throw new ServiceException("禁止访问超级管理员信息!");
}
if (!hasPermission) {
throw new ServiceException("没有权限访问用户数据!");
}
}9.2. 商业版本修复
提示
如果是v2.7.0及以后的版本,如果有演示账号fastbee,需要把fastbee账号的游客角色数据权限更改为仅本人数据权限
9.2.1. 情况一:如果代码仓库授权还未到期,则直接更新主分支代码即可
9.2.2. 情况二:代码仓库已过期,如果是v2.7.0及以后的版本参考以下代码修改
- com.fastbee.common.extend.utils.SecurityUtils#getDataScope 方法
public static String getDataScope() {
SysUser user = SecurityUtils.getLoginUser().getUser();
String dataScope;
if (user.isAdmin()) {
dataScope = DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD;
} else {
List<SysRole> roles = user.getRoles();
List<String> list = roles.stream().map(SysRole::getDataScope).distinct().collect(Collectors.toList());
if (list.contains(DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD)) {
dataScope = DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD;
} else if (list.contains(DataScopeAspect.DATA_SCOPE_DEPT)) {
dataScope = DataScopeAspect.DATA_SCOPE_DEPT;
} else {
dataScope = DataScopeAspect.DATA_SCOPE_SELF;
}
}
return dataScope;
}- com.fastbee.system.service.impl.SysDeptServiceImpl#checkDeptDataScope 方法
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
@Override
public void checkDeptDataScope(Long deptId)
{
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
SysDept dept = new SysDept();
dept.setDeptId(deptId);
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
if (StringUtils.isEmpty(depts))
{
throw new ServiceException("没有权限访问部门数据!");
}
if (null == curUser.getDeptId()) {
throw new ServiceException("没有权限访问部门数据!");
} else {
String dataScope = getDataScope();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope) || DataScopeAspect.DATA_SCOPE_DEPT.equals(dataScope)) {
if (!curUser.getDeptId().equals(deptId)) {
throw new ServiceException("没有权限访问部门数据!");
}
} else if (DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
if (!curUser.getDeptId().equals(deptId)) {
String ancestors = depts.get(0).getAncestors();
if (!ancestors.contains(curUser.getDeptId().toString())) {
throw new ServiceException("没有权限访问部门数据!");
}
}
}
}
}- com.fastbee.controller.system.SysDeptController#list 方法
/**
* 获取机构列表
*/
@ApiOperation("获取机构列表")
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list")
public AjaxResult list(SysDept dept)
{
if (Objects.nonNull(dept) && null != dept.getDeptId()) {
deptService.checkDeptDataScope(dept.getDeptId());
}
List<SysDept> depts = deptService.selectDeptList(dept);
return success(depts);
}- com.fastbee.controller.system.SysDeptController#getInfo 方法
/**
* 根据机构编号获取详细信息
*/
@ApiOperation("根据机构编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId)
{
deptService.checkDeptDataScope(deptId);
SysDept sysDept = deptService.selectDeptById(deptId);
if (null != sysDept && null != sysDept.getDeptUserId()) {
SysUser sysUser = sysUserService.selectUserById(sysDept.getDeptUserId());
sysDept.setUserName(sysUser.getUserName());
sysDept.setPhone(sysUser.getPhonenumber());
}
return success(sysDept);
}- com.fastbee.controller.system.SysDeptController#getRole 方法
/**
* 获取机构角色
* @param deptId 机构id
* @return com.fastbee.common.core.domain.AjaxResult
*/
@GetMapping("/getRole")
public AjaxResult getRole(Long deptId) {
deptService.checkDeptDataScope(deptId);
String dataScope = getDataScope();
AjaxResult success = AjaxResult.success();
List<SysRole> sysRoleList = deptService.getRole(deptId);
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
List<Long> roleIdList = getLoginUser().getUser().getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList());
sysRoleList = sysRoleList.stream().filter(sysRole -> roleIdList.contains(sysRole.getRoleId())).collect(Collectors.toList());
} else {
if (!isAdmin(getUserId()) && CollectionUtils.isNotEmpty(sysRoleList)) {
sysRoleList = sysRoleList.stream().filter(sysRole -> !"admin".equals(sysRole.getRoleKey())).collect(Collectors.toList());
}
}
success.put("roles", sysRoleList);
success.put("roleIds", sysRoleList.stream().map(SysRole::getRoleId).collect(Collectors.toList()));
return success;
}- com.fastbee.system.service.impl.SysUserServiceImpl#checkUserDataScope 方法
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
@Override
public void checkUserDataScope(Long userId) {
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
if (curUser.getUserId().equals(userId)) {
return;
}
if (SysUser.isAdmin(userId)) {
throw new ServiceException("没有权限访问用户数据!");
}
SysUser user = SpringUtils.getAopProxy(this).selectUserById(userId);
if (ObjectUtil.isNull(user)) {
throw new ServiceException("没有权限访问用户数据!");
}
if (null == curUser.getDeptId() || null == user.getDeptId()) {
throw new ServiceException("没有权限访问用户数据!");
}
String dataScope = getDataScope();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
throw new ServiceException("没有权限访问用户数据!");
} else if (DataScopeAspect.DATA_SCOPE_DEPT.equals(dataScope)) {
if (!curUser.getDeptId().equals(user.getDeptId())) {
throw new ServiceException("没有权限访问用户数据!");
}
} else if (DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
if (!curUser.getDeptId().equals(user.getDeptId())) {
String ancestors = user.getDept().getAncestors();
if (!ancestors.contains(curUser.getDeptId().toString())) {
throw new ServiceException("没有权限访问用户数据!");
}
}
}
List<SysRole> roles = curUser.getRoles();
List<String> roleKeyList = roles.stream().map(SysRole::getRoleKey).collect(Collectors.toList());
if (!roleKeyList.contains("manager") && user.getDept().getDeptUserId().equals(userId)) {
throw new ServiceException("没有权限访问用户数据!");
}
}- com.fastbee.controller.system.SysUserController#list 方法
/**
* 获取用户列表
*/
@ApiOperation("获取用户分页列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
if (null != user.getDeptId()) {
deptService.checkDeptDataScope(user.getDeptId());
String dataScope = getDataScope();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
user.setUserId(getUserId());
}
}
Page<SysUser> list = sysUserService.selectUserList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysUserController#export 方法
@ApiOperation("导出用户列表")
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user)
{
if (null != user.getDeptId()) {
deptService.checkDeptDataScope(user.getDeptId());
String dataScope = getDataScope();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
user.setUserId(getUserId());
}
}
Page<SysUser> list = sysUserService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.exportExcel(response, list.getRecords(), "用户数据");
}- com.fastbee.controller.system.SysUserController#authRole 方法
/**
* 根据用户编号获取授权角色
*/
@ApiOperation("根据用户编号获取授权角色")
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
sysUserService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success();
SysUser user = sysUserService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user);
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax;
}- com.fastbee.controller.system.SysUserController#insertAuthRole 方法
/**
* 用户授权角色
*/
@ApiOperation("为用户授权角色")
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
sysUserService.checkUserDataScope(userId);
SysUser sysUser = sysUserService.selectSysUserById(userId);
List<Long> deptRoleIds = sysRoleDeptMapper.selectByDeptId(sysUser.getDeptId());
boolean b = deptRoleIds.removeAll(Arrays.asList(roleIds));
if (!b) {
return error("请检查角色id");
}
sysUserService.insertUserAuth(userId, roleIds);
return success();
}- com.fastbee.controller.system.SysUserController#deptTree 方法
/**
* 获取部门树列表
*/
@ApiOperation("获取部门树列表")
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
if (Objects.nonNull(dept) && null != dept.getDeptId()) {
deptService.checkDeptDataScope(dept.getDeptId());
}
return success(deptService.selectDeptTreeList(dept));
}- com.fastbee.controller.system.SysUserController#listTerminal 方法
/**
* 获取终端用户列表
* @param user 用户信息
* @return com.fastbee.common.core.page.TableDataInfo
*/
@ApiOperation("获取用户分页列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/listTerminal")
public TableDataInfo listTerminal(SysUser user)
{
if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
return new TableDataInfo();
}
Page<SysUser> page = sysUserService.listTerminal(user);
return getDataTable(page.getRecords(), page.getTotal());
}- com.fastbee.system.service.impl.SysUserServiceImpl#selectByDeptId 方法
/**
* 根据机构id获取当前机构所有非管理用户
*/
@Override
public Page<SysUser> selectByDeptId(SysUser user) {
Long deptId = SecurityUtils.getDeptId();
MPJLambdaWrapper<SysUser> wrapper = JoinWrappers.lambda(SysUser.class);
// select
wrapper.select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUserName,
SysUser::getNickName);
// join
wrapper.innerJoin(SysDept.class, SysDept::getDeptId, SysUser::getDeptId);
// where
String dataScope = getDataScope();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
wrapper.eq(SysUser::getUserId, user.getUserId());
} else {
wrapper.eq(SysUser::getDeptId, deptId);
wrapper.ne(SysUser::getDeptId, SysDept::getDeptUserId);
}
return baseMapper.selectPage(new Page<>(1, Integer.MAX_VALUE), wrapper);
}- com.fastbee.system.service.impl.SysRoleServiceImpl#checkRoleDataScope 方法
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
@Override
public void checkRoleDataScope(Long roleId) {
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
List<SysRole> roles = curUser.getRoles();
List<Long> roleIdList = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
if (roleIdList.contains(roleId)) {
return;
}
if (null == curUser.getDeptId()) {
throw new ServiceException("没有权限访问角色数据!");
} else {
String dataScope = getDataScope();
LambdaQueryWrapper<SysRoleDept> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRoleDept::getRoleId, roleId);
List<SysRoleDept> sysRoleDepts = roleDeptMapper.selectList(queryWrapper);
SysRoleDept sysRoleDept = sysRoleDepts.get(0);
if (Objects.isNull(sysRoleDept)) {
throw new ServiceException("没有权限访问角色数据!");
}
Long bindDeptId = sysRoleDept.getDeptId();
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
throw new ServiceException("没有权限访问角色数据!");
} else if (DataScopeAspect.DATA_SCOPE_DEPT.equals(dataScope)) {
if (!curUser.getDeptId().equals(bindDeptId)) {
throw new ServiceException("没有权限访问角色数据!");
}
} else if (DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
if (!curUser.getDeptId().equals(bindDeptId)) {
SysDept sysDept = sysDeptMapper.selectDeptById(bindDeptId);
String ancestors = sysDept.getAncestors();
if (!ancestors.contains(curUser.getDeptId().toString())) {
throw new ServiceException("没有权限访问角色数据!");
}
}
}
}
}- com.fastbee.system.service.impl.SysRoleServiceImpl#selectRoleList 方法
/**
* 根据条件分页查询角色数据
*
* @param role 角色信息
* @return 角色数据集合信息
*/
@Override
// @DataScope(deptAlias = "d")
public Page<SysRole> selectRoleList(SysRole role) {
LoginUser loginUser = getLoginUser();
Long userId = loginUser.getUserId();
Long userDeptId = loginUser.getDeptId();
String dataScope = getDataScope();
Page<SysRole> rolePage;
if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
List<Long> roleIdList = loginUser.getUser().getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList());
rolePage = roleMapper.selectRoleByIds(new Page<>(role.getPageNum(), role.getPageSize()), roleIdList, role.getRoleName(), role.getStatus());
if (0 == rolePage.getTotal()) {
return rolePage;
}
List<SysRole> sysRoleList = rolePage.getRecords();
SysDept dept = loginUser.getUser().getDept();
for (SysRole sysRole : sysRoleList) {
if (Objects.nonNull(dept)) {
sysRole.setDeptId(dept.getDeptId());
sysRole.setDeptName(dept.getDeptName());
}
sysRole.setManager("manager".equals(sysRole.getRoleKey()));
}
return rolePage;
} else {
SysDept sysDept = new SysDept();
sysDept.setDeptId(role.getDeptId());
List<SysDept> sysDeptList = deptService.selectDeptList(sysDept);
if (CollectionUtils.isNotEmpty(sysDeptList)) {
Map<Long, String> deptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
List<Long> deptIdList = sysDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
List<SysRoleDeptVO> sysRoleDeptVOList = roleDeptMapper.selectRoleDeptByDeptIds(deptIdList);
Map<Long, SysRoleDeptVO> roleDeptMap = sysRoleDeptVOList.stream().collect(Collectors.toMap(SysRoleDeptVO::getRoleId, Function.identity()));
if (CollectionUtils.isEmpty(sysRoleDeptVOList)) {
return new Page<>();
}
List<Long> roleIdList = sysRoleDeptVOList.stream().map(SysRoleDeptVO::getRoleId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleIdList)) {
return new Page<>();
}
rolePage = roleMapper.selectRoleByIds(new Page<>(role.getPageNum(), role.getPageSize()), roleIdList, role.getRoleName(), role.getStatus());
List<SysRole> sysRoleList = rolePage.getRecords();
for (SysRole sysRole : sysRoleList) {
SysRoleDeptVO sysRoleDeptVO = roleDeptMap.get(sysRole.getRoleId());
Long deptId1 = sysRoleDeptVO.getDeptId();
String deptName = deptMap.get(deptId1);
sysRole.setDeptId(deptId1);
sysRole.setDeptName(deptName);
sysRole.setCanEditRole(!(userDeptId.equals(deptId1) && "manager".equals(sysRole.getRoleKey()) && !isAdmin(userId)));
if (isAdmin(sysRoleDeptVO.getDeptUserId())) {
sysRole.setManager("terminalRegister".equals(sysRole.getRoleKey()) || "scadaShare".equals(sysRole.getRoleKey())
|| "manager".equals(sysRole.getRoleKey()) || "webRegister".equals(sysRole.getRoleKey()));
} else {
sysRole.setManager("manager".equals(sysRole.getRoleKey()));
}
}
return rolePage;
} else {
return new Page<>();
}
}
}- com.fastbee.controller.system.SysRoleController#list 方法
@ApiOperation("获取角色分页列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role, Integer pageNum, Integer pageSize)
{
if (null != role.getDeptId()) {
deptService.checkDeptDataScope(role.getDeptId());
}
role.setPageNum(pageNum);
role.setPageSize(pageSize);
Page<SysRole> rolePage = sysRoleService.selectRoleList(role);
// 按照 roleSort 字段排序
rolePage.getRecords().sort(Comparator.comparingInt(SysRole::getRoleSort));
TableDataInfo tableDataInfo = new TableDataInfo();
tableDataInfo.setCode(HttpStatus.SUCCESS);
tableDataInfo.setMsg(MessageUtils.message("query.success"));
tableDataInfo.setRows(rolePage.getRecords());
tableDataInfo.setTotal(rolePage.getTotal());
return tableDataInfo;
}- com.fastbee.controller.system.SysRoleController#export 方法
@ApiOperation("导出角色列表")
@Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysRole role)
{
if (null != role.getDeptId()) {
deptService.checkDeptDataScope(role.getDeptId());
}
List<SysRole> list = sysRoleService.selectRoleList(role).getRecords();
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
util.exportExcel(response, list, "角色数据");
}- com.fastbee.controller.system.SysRoleController#optionselect 方法
/**
* 获取角色选择框列表
*/
@ApiOperation("获取角色选择框列表")
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
SysRole sysRole = new SysRole();
sysRole.setPageNum(1);
sysRole.setPageSize(99);
Page<SysRole> rolePage = sysRoleService.selectRoleList(sysRole);
return success(rolePage.getRecords());
}- com.fastbee.controller.system.SysRoleController#allocatedList 方法
/**
* 查询已分配用户角色列表
*/
@ApiOperation("查询已分配用户角色列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user)
{
if (null != user.getRoleId()) {
sysRoleService.checkRoleDataScope(user.getRoleId());
}
Page<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysRoleController#unallocatedList 方法
/**
* 查询未分配用户角色列表
*/
@ApiOperation("查询未分配用户角色列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user)
{
if (null != user.getRoleId()) {
sysRoleService.checkRoleDataScope(user.getRoleId());
}
Page<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysRoleController#cancelAuthUser 方法
/**
* 取消授权用户
*/
@ApiOperation("取消授权用户")
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{
if (null != userRole.getRoleId()) {
sysRoleService.checkRoleDataScope(userRole.getRoleId());
}
return toAjax(sysRoleService.deleteAuthUser(userRole));
}- com.fastbee.controller.system.SysRoleController#cancelAuthUserAll 方法
/**
* 批量取消授权用户
*/
@ApiOperation("批量取消授权用户")
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{
if (null != roleId) {
sysRoleService.checkRoleDataScope(roleId);
}
return toAjax(sysRoleService.deleteAuthUsers(roleId, userIds));
}- com.fastbee.controller.system.SysRoleController#deptTree 方法
/**
* 获取对应角色部门树列表
*/
@ApiOperation("获取对应角色部门树列表")
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{
sysRoleService.checkRoleDataScope(roleId);
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax;
}9.2.3. 情况三:代码仓库已过期,如果是v2.3~v2.6.0的版本参考以下代码做修改
- com.fastbee.system.service.impl.SysDeptServiceImpl#checkDeptDataScope 方法
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
@Override
public void checkDeptDataScope(Long deptId)
{
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
SysDept dept = new SysDept();
dept.setDeptId(deptId);
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
if (StringUtils.isEmpty(depts))
{
throw new ServiceException("没有权限访问部门数据!");
}
if (null == curUser.getDeptId()) {
throw new ServiceException("没有权限访问部门数据!");
} else {
if (!curUser.getDeptId().equals(deptId)) {
throw new ServiceException("没有权限访问部门数据!");
}
}
}- com.fastbee.controller.system.SysDeptController#list 方法
/**
* 获取机构列表
*/
@ApiOperation("获取机构列表")
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list")
public AjaxResult list(SysDept dept)
{
if (Objects.nonNull(dept) && null != dept.getDeptId()) {
deptService.checkDeptDataScope(dept.getDeptId());
}
List<SysDept> depts = deptService.selectDeptList(dept);
return success(depts);
}- com.fastbee.controller.system.SysDeptController#getRole 方法
/**
* 获取机构角色
* @param deptId 机构id
* @return com.fastbee.common.core.domain.AjaxResult
*/
@GetMapping("/getRole")
public AjaxResult getRole(Long deptId) {
deptService.checkDeptDataScope(deptId);
AjaxResult success = AjaxResult.success();
List<SysRole> sysRoleList = deptService.getRole(deptId);
if (!isAdmin(getUserId()) && CollectionUtils.isNotEmpty(sysRoleList)) {
sysRoleList = sysRoleList.stream().filter(sysRole -> !"admin".equals(sysRole.getRoleKey())).collect(Collectors.toList());
}
success.put("roles", sysRoleList);
success.put("roleIds", sysRoleList.stream().map(SysRole::getRoleId).collect(Collectors.toList()));
return success;
}- com.fastbee.system.service.impl.SysUserServiceImpl#checkUserDataScope 方法
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
@Override
public void checkUserDataScope(Long userId) {
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
if (curUser.getUserId().equals(userId)) {
return;
}
if (SysUser.isAdmin(userId)) {
throw new ServiceException("没有权限访问用户数据!");
}
SysUser user = SpringUtils.getAopProxy(this).selectUserById(userId);
if (ObjectUtil.isNull(user)) {
throw new ServiceException("没有权限访问用户数据!");
}
if (null == curUser.getDeptId() || null == user.getDeptId()) {
throw new ServiceException("没有权限访问用户数据!");
}
if (!curUser.getDeptId().equals(user.getDeptId())) {
throw new ServiceException("没有权限访问用户数据!");
}
List<SysRole> roles = curUser.getRoles();
List<String> roleKeyList = roles.stream().map(SysRole::getRoleKey).collect(Collectors.toList());
if (!roleKeyList.contains("manager") && user.getDept().getDeptUserId().equals(userId)) {
throw new ServiceException("没有权限访问用户数据!");
}
}- com.fastbee.controller.system.SysUserController#list 方法
/**
* 获取用户列表
*/
@ApiOperation("获取用户分页列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
if (null == user.getDeptId()) {
user.setDeptId(getLoginUser().getDeptId());
} else {
deptService.checkDeptDataScope(user.getDeptId());
}
if (null != user.getUserId()) {
sysUserService.checkUserDataScope(user.getUserId());
}
if (null == user.getShowChild()) {
user.setShowChild(true);
}
Page<SysUser> list = sysUserService.selectUserList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysUserController#export 方法
@ApiOperation("导出用户列表")
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user)
{
if (null == user.getDeptId()) {
user.setDeptId(getLoginUser().getDeptId());
} else {
deptService.checkDeptDataScope(user.getDeptId());
}
if (null != user.getUserId()) {
sysUserService.checkUserDataScope(user.getUserId());
}
if (null == user.getShowChild()) {
user.setShowChild(true);
}
Page<SysUser> list = sysUserService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.exportExcel(response, list.getRecords(), "用户数据");
}- com.fastbee.controller.system.SysUserController#authRole 方法
/**
* 根据用户编号获取授权角色
*/
@ApiOperation("根据用户编号获取授权角色")
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
sysUserService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success();
SysUser user = sysUserService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user);
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax;
}- com.fastbee.controller.system.SysUserController#insertAuthRole 方法
/**
* 用户授权角色
*/
@ApiOperation("为用户授权角色")
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
sysUserService.checkUserDataScope(userId);
SysUser sysUser = sysUserService.selectSysUserById(userId);
List<Long> deptRoleIds = sysRoleDeptMapper.selectByDeptId(sysUser.getDeptId());
boolean b = deptRoleIds.removeAll(Arrays.asList(roleIds));
if (!b) {
return error("请检查角色id");
}
sysUserService.insertUserAuth(userId, roleIds);
return success();
}- com.fastbee.controller.system.SysUserController#deptTree 方法
/**
* 获取部门树列表
*/
@ApiOperation("获取部门树列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
if (Objects.nonNull(dept) && null != dept.getDeptId()) {
deptService.checkDeptDataScope(dept.getDeptId());
}
return success(deptService.selectDeptTreeList(dept));
}- com.fastbee.controller.system.SysUserController#listTerminal 方法
/**
* 获取终端用户列表
* @param user 用户信息
* @return com.fastbee.common.core.page.TableDataInfo
*/
@ApiOperation("获取用户分页列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/listTerminal")
public TableDataInfo listTerminal(SysUser user)
{
if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
return new TableDataInfo();
}
Page<SysUser> page = sysUserService.listTerminal(user);
return getDataTable(page.getRecords(), page.getTotal());
}- com.fastbee.system.service.impl.SysRoleServiceImpl#checkRoleDataScope 方法
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
@Override
public void checkRoleDataScope(Long roleId) {
LoginUser loginUser = getLoginUser();
SysUser curUser = loginUser.getUser();
if (SysUser.isAdmin(curUser.getUserId())) {
return;
}
List<SysRole> roles = curUser.getRoles();
List<Long> roleIdList = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
if (roleIdList.contains(roleId)) {
return;
}
if (null == curUser.getDeptId()) {
throw new ServiceException("没有权限访问角色数据!");
} else {
LambdaQueryWrapper<SysRoleDept> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRoleDept::getRoleId, roleId);
List<SysRoleDept> sysRoleDeptList = roleDeptMapper.selectList(queryWrapper);
SysRoleDept sysRoleDept = sysRoleDeptList.get(0);
if (Objects.isNull(sysRoleDept)) {
throw new ServiceException("没有权限访问角色数据!");
}
if (!curUser.getDeptId().equals(sysRoleDept.getDeptId())) {
throw new ServiceException("没有权限访问角色数据!");
}
}
}- com.fastbee.controller.system.SysRoleController#list 方法
@ApiOperation("获取角色分页列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role, Integer pageNum, Integer pageSize)
{
if (null != role.getDeptId()) {
deptService.checkDeptDataScope(role.getDeptId());
}
role.setPageNum(pageNum);
role.setPageSize(pageSize);
Page<SysRole> rolePage = sysRoleService.selectRoleList(role);
// 按照 roleSort 字段排序
rolePage.getRecords().sort(Comparator.comparingInt(SysRole::getRoleSort));
TableDataInfo tableDataInfo = new TableDataInfo();
tableDataInfo.setCode(HttpStatus.SUCCESS);
tableDataInfo.setMsg(MessageUtils.message("query.success"));
tableDataInfo.setRows(rolePage.getRecords());
tableDataInfo.setTotal(rolePage.getTotal());
return tableDataInfo;
}- com.fastbee.controller.system.SysRoleController#export 方法
@ApiOperation("导出角色列表")
@Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')")
@PostMapping("/export")
public void export(HttpServletResponse response, SysRole role)
{
if (null != role.getDeptId()) {
deptService.checkDeptDataScope(role.getDeptId());
}
List<SysRole> list = sysRoleService.selectRoleList(role).getRecords();
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
util.exportExcel(response, list, "角色数据");
}- com.fastbee.controller.system.SysRoleController#optionselect 方法
/**
* 获取角色选择框列表
*/
@ApiOperation("获取角色选择框列表")
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
Long deptId = getDeptId();
if (null == deptId) {
return success();
}
return success(sysRoleService.selectRoleAll());
}- com.fastbee.controller.system.SysRoleController#allocatedList 方法
/**
* 查询已分配用户角色列表
*/
@ApiOperation("查询已分配用户角色列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user)
{
if (null != user.getRoleId()) {
sysRoleService.checkRoleDataScope(user.getRoleId());
}
Page<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysRoleController#unallocatedList 方法
/**
* 查询未分配用户角色列表
*/
@ApiOperation("查询未分配用户角色列表")
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user)
{
if (null != user.getRoleId()) {
sysRoleService.checkRoleDataScope(user.getRoleId());
}
Long deptId = getDeptId();
if (null == deptId) {
return new TableDataInfo();
}
if (null != user.getDeptId()) {
deptService.checkDeptDataScope(deptId);
}
Page<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list.getRecords(), list.getTotal());
}- com.fastbee.controller.system.SysRoleController#cancelAuthUser 方法
/**
* 取消授权用户
*/
@ApiOperation("取消授权用户")
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{
if (null != userRole.getRoleId()) {
sysRoleService.checkRoleDataScope(userRole.getRoleId());
}
return toAjax(sysRoleService.deleteAuthUser(userRole));
}- com.fastbee.controller.system.SysRoleController#cancelAuthUserAll 方法
/**
* 批量取消授权用户
*/
@ApiOperation("批量取消授权用户")
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{
if (null != roleId) {
sysRoleService.checkRoleDataScope(roleId);
}
return toAjax(sysRoleService.deleteAuthUsers(roleId, userIds));
}- com.fastbee.controller.system.SysRoleController#deptTree 方法
/**
* 获取对应角色部门树列表
*/
@ApiOperation("获取对应角色部门树列表")
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{
sysRoleService.checkRoleDataScope(roleId);
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax;
}

