Skip to content

敏感词 ​

这篇解决什么 ​

IM 私聊、群聊的文本不能直接入库。读完能改词库表、validateText、租户缓存,以及在其它文本入口接上同一套拦截。

默认端口 48080,管理端前缀 /admin-api。菜单在 IM 即时通讯 → 敏感词管理,路由 /im/sensitive-word。

示意图:发文本先过 validateText;词库按租户缓存,匹配交给 houbb SensitiveWordBs。

只拦文本,不改已入库消息

ImContentTypeEnum.TEXT(101)才会调用。图片、语音、视频、表情不走这层。命中抛 MESSAGE_SENSITIVE_WORD_BLOCKED,消息不会 insert。

组件位置 ​

名称说明仓库路径
ImSensitiveWordManagerController@RequestMapping("/im/manager/sensitive-word"),词库 CRUDruoyi-office/yudao-module-im/yudao-module-im-server/.../controller/admin/manager/sensitiveword/ImSensitiveWordManagerController.java
ImSensitiveWordServicevalidateText(text);空白直接返回同模块 .../service/sensitiveword/ImSensitiveWordService.java
ImSensitiveWordServiceImpl租户 LoadingCache + houbb trieImSensitiveWordServiceImpl.java
管理端列表useVbenVxeGrid,新增 / 批量删除ruoyi-office-vben/apps/web-antd/src/views/im/manager/sensitiveword/index.vue
管理端 API/im/manager/sensitive-word/*.../src/api/im/manager/sensitiveword/index.ts
Maven 依赖com.github.houbb:sensitive-word,版本 0.29.5ruoyi-office/yudao-dependencies/pom.xml、yudao-module-im-server/pom.xml

写操作挂 @PreAuthorize:im:manager:sensitive-word:create / update / delete。菜单权限是 im:manager:sensitive-word:list。

管理端词库 ​

打开 IM 即时通讯 → 敏感词管理。列表按词、状态、创建时间筛。点新增写入一条,停用后不再进检测树。

敏感词列表

本系统截图:敏感词列表。词库为空时显示「暂无数据」。

新增敏感词

本系统截图:新增弹窗。必填词本身和状态(开启 / 关闭)。

名称说明仓库路径
新增 / 修改word 最长 64;status 走 CommonStatusEnumImSensitiveWordSaveReqVO.java
分页word 模糊、status、createTime 区间ImSensitiveWordPageReqVO.java
列表填充创建人/page 用 AdminUserApi.getUserMap 补 creatorNameImSensitiveWordManagerController
移动端页同菜单,路径 /pages-im/manager/sensitive-word/indexruoyi-office-uniapp/src/pages-im/manager/sensitive-word/

管理端没有「试一下这段话」的接口。要验证命中,发一条私聊 / 群聊文本,或在单测里调 validateText。

同租户词不能重复

(word, tenant_id) 唯一。重复抛 SENSITIVE_WORD_DUPLICATED。改词时排除自身。

表与字段 ​

ImSensitiveWordDO 映射 im_sensitive_word。检测只读 status = 0 的行。

名称说明仓库路径
@TableName("im_sensitive_word")IM 敏感词表.../dal/dataobject/sensitiveword/ImSensitiveWordDO.java
word词本身。表列 varchar(128),入参仍按 VO 限 64同上
status0 启用,1 停用CommonStatusEnum
uk_im_sensitive_word(word, tenant_id)ruoyi-office-db/dump/latest/ 中该表 DDL
selectListByStatus重建 trie 时只拉启用词ImSensitiveWordMapper.java
selectMaxUpdateTime缓存刷新比对基线同上
java
@TableName("im_sensitive_word")
@KeySequence("im_sensitive_word_seq")
public class ImSensitiveWordDO extends BaseDO {
    @TableId
    private Long id;
    private String word;
    private Integer status;
}

BaseDO 带 creator / createTime / updater / updateTime / deleted / tenant_id。不要另加标签列,当前没有按场景分组。

发消息时过滤 ​

私聊、群聊在校验好友 / 群成员之后、insert 之前,对文本调用 validateText。

java
if (ImContentTypeEnum.TEXT.getType().equals(reqVO.getType())) {
    sensitiveWordService.validateText(reqVO.getContent());
}
名称说明仓库路径
私聊sendPrivateMessage 1.4 步.../service/message/ImPrivateMessageServiceImpl.java
群聊sendGroupMessage 1.5 步ImGroupMessageServiceImpl.java
validateText空白跳过;bs.contains(text) 为 true 则抛错ImSensitiveWordServiceImpl
MESSAGE_SENSITIVE_WORD_BLOCKED1_040_300_004,「消息包含敏感词,无法发送」.../enums/ErrorCodeConstants.java

构建检测器时打开了忽略大小写、全半角、数字风格、繁简体。「違禁」 和 违禁 会按同一套规则命中。

不要自己 replace 后再入库

这里是拦截,不是打码。要在 JSON 里挡手机号、身份证,走 数据脱敏,不要把 validateText 当成掩码工具。

词库缓存 ​

每个租户一份 SensitiveWordBs。首次 validateText 才加载。CRUD 后本机立刻 invalidate;其它实例靠 1 分钟异步 reload,先比 max(update_time),没变就不重建。

名称说明仓库路径
sensitiveWordBsCachesCacheUtils.buildAsyncReloadingCache,1 分钟ImSensitiveWordServiceImpl
loadFresh先取 max(update_time),再读启用词,最后 SensitiveWordBs.init()同上
reload无租户上下文,必须 TenantUtils.execute(tenantId, …)同上
本机失效有租户只失效当前租户;没有则 invalidateAllinvalidateSensitiveWordBsCaches

单测在 ImSensitiveWordServiceImplTest:空文本放过、命中抛错、增删后下次校验换词库。

刷新线程要带租户

reload 跑在缓存线程,没有 TenantContextHolder。漏掉 TenantUtils.execute,租户拦截器会按空上下文拼 SQL,读到错库或空词库。

接到其它文本 ​

评论、群公告、频道标题若也要拦,注入 ImSensitiveWordService,在写库前调用 validateText。不要再抄一套 trie。

java
@Resource
private ImSensitiveWordService sensitiveWordService;

public void check(String text) {
    sensitiveWordService.validateText(text);
}
名称说明仓库路径
过滤入口当前模块内 Service,不是独立 Feign APIImSensitiveWordService
词库 CRUD仍走 /im/manager/sensitive-wordController 见上文
权限标识按钮级,见权限篇的 @ss.hasPermissionim:manager:sensitive-word:*

跨模块不要反向依赖 IM。只在 IM 自己的文本链路上复用这个 Service。

配置与操作 ​

词库在 IM → 敏感词管理(/im/sensitive-word),表 im_sensitive_word。框架没有敏感词 Starter,跨模块不要依赖 IM。

开启见 框架层。截图见上文列表。

相关篇 ​

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版