sensitive-word-admin
sensitive-word-admin 是基于 sensitive-word 实现的, 一款开箱即用的敏感词控台服务。
特性
基本的 CRUD* 开箱即用的配置控台* 简单易用的 API 服务> 变更日志
快速开始
数据库脚本
执行 mysql-5.7.sql 脚本。
核心表如下:
create table word
(id int unsigned auto_increment comment '应用自增主键' primary key,word varchar(128) not null comment '单词',type varchar(8) not null comment '类型',status char(1) not null default 'S' comment '状态',remark varchar(64) not null comment '配置描述' default '',operator_id varchar(64) not null default 'system' comment '操作员名称',create_time timestamp default CURRENT_TIMESTAMP not null comment '创建时间戳',update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间戳'
) comment '敏感词表' ENGINE=Innodb default charset=UTF8 auto_increment=1;
create unique index uk_word on word (word) comment '唯一索引';
应用启动
直接运行 Applicaiton#main() 启动应用,启动日志如下:
2021-07-20 20:56:48.200 INFO [] 6680 --- [ main] o.a.coyote.http11.Http11NioProtocol: Starting ProtocolHandler ["http-nio-8080"]
2021-07-20 20:56:48.219 INFO [] 6680 --- [ main] o.a.tomcat.util.net.NioSelectorPool: Using a shared selector for servlet write/read
2021-07-20 20:56:48.248 INFO [] 6680 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2021-07-20 20:56:48.256 INFO [] 6680 --- [ main] c.g.h.sensitive.word.admin.Application : Started Application in 14.04 seconds (JVM running for 15.82)
敏感词配置
除了 sensitive-word 本身自带的敏感词外,我们可以根据自己的业务进行配置。
类型分为两种:禁止和允许。禁止说明是敏感词,允许说明不认为是敏感词。
所有的类型,只要在状态为正常的情况下才会生效。
测试验证
contains
是否包含敏感词。
http://localhost:8080/api/sensitiveWord/contains?text=凡凡做测试
返回:
{"respCode":"0000","respMessage":"成功","result":true}
findAll
找到所有的敏感词。
http://localhost:8080/api/sensitiveWord/findAll?text=凡凡做测试
返回:
{"respCode":"0000","respMessage":"成功","total":2,"list":["凡凡","测试"]}
replace
替换对应的敏感词。
http://localhost:8080/api/sensitiveWord/replace?text=凡凡做测试
返回:
{"respCode":"0000","respMessage":"成功","result":"**做**"}
所有的结果可以根据控台更改,实时生效。
实现原理
底层依赖
依赖 github.com/houbb/sensi… 提供的敏感词工具。
因为原来的工具只有一些最基本的功能,无法根据配置动态变化,不符合实际应用场景。
所以在原有的基础上实现了一个开箱即用的控台,并且提供了简单的 API。
对于敏感词工具本身,本篇不做介绍,推荐阅读:
敏感词使用入门介绍
技术选型
springboot
mybatis-plus
vue
基于数据库的敏感词
自定义的敏感词相关数据存储在数据库,对应的定义如下:
/**
* 自定义敏感词
*
* @author 老马啸西风
* @since 1.1.0
*/
@Component
public class MyDdWordDeny implements IWordDeny {@Autowiredprivate WordService wordService;@Overridepublic List<String> deny() {Wrapper<Word> wordWrapper = new EntityWrapper<>();wordWrapper.eq("type", WordTypeEnum.DENY.getCode());wordWrapper.eq("status", WordStatusEnum.S.getCode());List<Word> wordList = wordService.selectList(wordWrapper);return CollectionUtil.toList(wordList, new IHandler<Word, String>() {@Overridepublic String handle(Word word) {return word.getWord();}});}
}
和
/**
* 自定义白名单
*
* @author 老马啸西风
* @since 1.1.0
*/
@Component
public class MyDdWordAllow implements IWordAllow {@Autowiredprivate WordService wordService;@Overridepublic List<String> allow() {Wrapper<Word> wordWrapper = new EntityWrapper<>();wordWrapper.eq("type", WordTypeEnum.ALLOW.getCode());wordWrapper.eq("status", WordStatusEnum.S.getCode());List<Word> wordList = wordService.selectList(wordWrapper);return CollectionUtil.toList(wordList, new IHandler<Word, String>() {@Overridepublic String handle(Word word) {return word.getWord();}});}
}
敏感词引导类初始化
对应的敏感类初始化也比较简单,我们在系统默认的基础上,添加上自定义的数据。
@Configuration
public class SensitiveWordConfig {@Autowiredprivate MyDdWordAllow myDdWordAllow;@Autowiredprivate MyDdWordDeny myDdWordDeny;/** * 初始化引导类 * @return 初始化引导类 * @since 1.0.0 */@Beanpublic SensitiveWordBs sensitiveWordBs() {return SensitiveWordBs.newInstance().wordAllow(WordAllows.chains(WordAllows.system(), myDdWordAllow)).wordDeny(WordDenys.chains(WordDenys.system(), myDdWordDeny)).ignoreRepeat(false)// 各种其他配置.init();}
}
配置变更及敏感词刷新
每一次敏感词配置发生变更的时候,我们都主动刷新一下敏感词词典信息。
/**
* <p>
* 敏感词表 前端控制器
* </p>
*
* @author 老马啸西风
* @since 2021-07-07
*/
@Controller
@RequestMapping("/word")
@TraceId
@AutoLog
public class WordController {@Autowiredprivate WordService wordService;@Autowiredprivate SensitiveWordBs sensitiveWordBs;/*** 首页*/@RequestMapping("/index")public String index() {return "word/index";}/*** 添加元素* @param entity 实体* @return 结果*/@RequestMapping("/add")@ResponseBodypublic BaseResp add(@RequestBody final Word entity) {wordService.insert(entity);refreshSensitiveWord();return RespUtil.success();}/*** 编辑* @param entity 实体* @return 结果*/@RequestMapping("/edit")@ResponseBodypublic BaseResp edit(final Word entity) {wordService.updateById(entity);refreshSensitiveWord();return RespUtil.success();}/*** 删除* @param id 实体* @return 结果*/@RequestMapping("/remove/{id}")@ResponseBodypublic BaseResp remove(@PathVariable final Integer id) {wordService.deleteById(id);refreshSensitiveWord();return RespUtil.success();}/** * 刷新敏感詞 * * 可以优化为异步,甚至批量。 * @since 1.1.0 */private void refreshSensitiveWord() {sensitiveWordBs.init();}
}
提供对外接口
这里提供的接口仅当做演示:
/**
* api 服务
* @author 老马啸西风
* @since 1.1.0
*/
@RestController
@RequestMapping("/api/sensitiveWord/")
@AutoLog
@TraceId
public class ApiSensitiveWordController {@Autowiredprivate SensitiveWordBs sensitiveWordBs;/** * 是否包含敏感词 * * @param text 文本 * @return 结果 */@RequestMapping("/contains")public BaseResp contains(@RequestParam("text") String text) { boolean contains = sensitiveWordBs.contains(text);return RespUtil.of(contains);}/** * 获取所有的敏感词 * @param text 文本 * @return 结果 */@RequestMapping("/findAll")public BaseResp findAll(@RequestParam("text") String text) {List<String> results = sensitiveWordBs.findAll(text);return RespUtil.of(results);}/** * 获取替换后的结果 * * @param text 文本 * @return 结果 */@RequestMapping("/replace")public BaseResp replace(@RequestParam("text") String text) {String results = sensitiveWordBs.replace(text);return RespUtil.of(results);}
}
如果实际我们真的对外部提供服务,肯定要比这个复杂的多,如果要考虑安全相关问题。
推荐阅读:
小结
敏感词的应用非常广泛,任何涉及到用户可以自由发言的地方,就需要考虑敏感词。
本文主要是为了演示如何基于 sensitive-word 实现一个开箱即用的敏感词服务,希望对你有所帮助。