SpringBoot使用SensitiveWord实现敏感词过滤

包含默认敏感词过滤和自定义敏感词过滤。

导入依赖

<dependency>
  <groupId>com.github.houbb</groupId>
  <artifactId>sensitive-word</artifactId>
  <version>0.2.0</version>
</dependency>

Github地址

方法

方法参数返回值说明
contains(String)待验证的字符串布尔值验证字符串是否包含敏感词
replace(String, ISensitiveWordReplace)使用指定的替换策略替换敏感词字符串返回脱敏后的字符串
replace(String, char)使用指定的 char 替换敏感词字符串返回脱敏后的字符串
replace(String)使用 * 替换敏感词字符串返回脱敏后的字符串
findAll(String)待验证的字符串字符串列表返回字符串中所有敏感词
findFirst(String)待验证的字符串字符串返回字符串中第一个敏感词
findAll(String, IWordResultHandler)IWordResultHandler 结果处理类字符串列表返回字符串中所有敏感词
findFirst(String, IWordResultHandler)IWordResultHandler 结果处理类字符串返回字符串中第一个敏感词

ISensitiveWordReplace:敏感词替换策略。

IWordResultHandler:结果处理。可以对敏感词的结果进行处理,允许用户自定义。内置了WordResultHandlers 工具类。

  • WordResultHandlers.word():只保留敏感词单词本身。
  • WordResultHandlers.raw():保留敏感词相关信息,包含敏感词以及敏感词对应的开始和结束下标。

默认示例

使用默认提供的方法。

@Test
void testWord() {
  String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
  System.out.println(SensitiveWordHelper.contains(text));

  System.out.println(SensitiveWordHelper.replace(text));
  System.out.println(SensitiveWordHelper.replace(text, '0'));

  System.out.println(SensitiveWordHelper.findFirst(text));
  System.out.println(SensitiveWordHelper.findFirst(text, WordResultHandlers.word()));
  System.out.println(SensitiveWordHelper.findFirst(text, WordResultHandlers.raw()));

  System.out.println(SensitiveWordHelper.findAll(text));
  System.out.println(SensitiveWordHelper.findAll(text, WordResultHandlers.word()));
  System.out.println(SensitiveWordHelper.findAll(text, WordResultHandlers.raw()));

}

输出:

Init sensitive word map end! Cost time: 163ms
true
****迎风飘扬,***的画像屹立在***前。
0000迎风飘扬,000的画像屹立在000前。
五星红旗
五星红旗
WordResult{word='五星红旗', startIndex=0, endIndex=4}
[五星红旗, 毛主席, 天安门]
[五星红旗, 毛主席, 天安门]
[WordResult{word='五星红旗', startIndex=0, endIndex=4}, WordResult{word='毛主席', startIndex=9, endIndex=12}, WordResult{word='天安门', startIndex=18, endIndex=21}]

自定义替换策略示例

采用自定义的替换策略实现。首先需要实现 ISensitiveWordReplace接口自定义替换策略:

package com.tothefor;

import com.github.houbb.heaven.util.lang.CharUtil;
import com.github.houbb.sensitive.word.api.ISensitiveWordReplace;
import com.github.houbb.sensitive.word.api.ISensitiveWordReplaceContext;

public class MySensitiveWordReplace implements ISensitiveWordReplace {

  @Override
  public String replace(ISensitiveWordReplaceContext context) {
    String sensitiveWord = context.sensitiveWord();
    // 自定义不同的敏感词替换策略,可以从数据库等地方读取
    if ("五星红旗".equals(sensitiveWord)) {
      return "旗帜";
    }

    if ("天安门".equals(sensitiveWord)) {
      return "门";
    }

    if ("毛主席".equals(sensitiveWord)) {
      return "教员";
    }
    // 其他默认使用 * 代替
    int wordLength = context.wordLength();
    return CharUtil.repeat('*', wordLength);
  }

}

使用:

@Test
void testWord() {
  String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
  System.out.println(SensitiveWordHelper.contains(text));
  System.out.println(SensitiveWordHelper.replace(text, new MySensitiveWordReplace()));

  String text1 = "最好的记忆不如最淡的墨水。";
  System.out.println(SensitiveWordHelper.contains(text1));
  System.out.println(SensitiveWordHelper.replace(text1, new MySensitiveWordReplace()));

}

输出:

Init sensitive word map end! Cost time: 16ms
true
旗帜迎风飘扬,教员的画像屹立在门前。
false
最好的记忆不如最淡的墨水。

自定义

点进 SensitiveWordHelper 源码,可以看见以下代码:

private static final SensitiveWordBs WORD_BS = SensitiveWordBs.newInstance().init();

而且可以发现,方法也都是调用的 SensitiveWordBs 类的方法。所以,可以理解成 SensitiveWordHelper 只是对 SensitiveWordBs 的一层封装,而之所以封装就是为了提供给开发者针对简单场景的快速的使用。

而且从上面的创建语句中可以看见,没有加任何其他的东西,就只是初始化了一个,这也是最简单的。接下来就是自定义 SensitiveWordBs 实现敏感词过滤。

自定义SensitiveWordBs

下来看有哪些参数可以加,各项配置的说明如下:

序号方法说明
1ignoreCase忽略大小写
2ignoreWidth忽略半角圆角
3ignoreNumStyle忽略数字的写法
4ignoreChineseStyle忽略中文的书写格式
5ignoreEnglishStyle忽略英文的书写格式
6ignoreRepeat忽略重复词
7enableNumCheck是否启用数字检测。默认连续 8 位数字认为是敏感词
8enableEmailCheck是有启用邮箱检测
9enableUrlCheck是否启用链接检测

然后创建自定义的 SensitiveWordBs,如下:

package com.tothefor.motorcode.core.SensitiveWord;

import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
import com.github.houbb.sensitive.word.support.allow.WordAllows;
import com.github.houbb.sensitive.word.support.deny.WordDenys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SensitiveWordConfig {

  @Autowired
  private CustomWordAllow customWordAllow;

  @Autowired
  private CustomWordDeny customWordDeny;

  /**
     * 初始化引导类
     *
     * @return 初始化引导类
     * @since 1.0.0
     */
  @Bean
  public SensitiveWordBs sensitiveWordBs() {
    // 可根据数据库数据判断 动态增加配置
    return SensitiveWordBs.newInstance()
      .wordDeny(WordDenys.chains(WordDenys.system(),customWordDeny)) // 设置黑名单
      .wordAllow(WordAllows.chains(WordAllows.system(), customWordAllow)) // 设置白名单
      .ignoreCase(true)
      .ignoreWidth(true)
      .ignoreNumStyle(true)
      .ignoreChineseStyle(true)
      .ignoreEnglishStyle(true)
      .ignoreRepeat(true)
      .enableEmailCheck(true)
      .enableUrlCheck(true)
      // 各种其他配置
      .init();
  }

}

其中,wordDeny、wordAllow是自定义敏感词的黑名单和白名单。可以设置单个,也可以设置多个。如下:

// 设置系统默认敏感词
SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
     .wordDeny(WordDenys.system()) // 黑名单
     .wordAllow(WordAllows.system()) // 白名单
     .init();

// 设置自定义敏感词
SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
     .wordDeny(new MyWordDeny())
     .wordAllow(new MyWordAllow())
     .init();

// 设置多个敏感词,系统默认和自定义
IWordDeny wordDeny = WordDenys.chains(WordDenys.system(), new MyWordDeny());
IWordAllow wordAllow = WordAllows.chains(WordAllows.system(), new MyWordAllow());
SensitiveWordBs wordBs = SensitiveWordBs.newInstance()
     .wordDeny(wordDeny)
     .wordAllow(wordAllow)
     .init();

接下来再加自定义敏感词配置。

自定义敏感词白名单

自定义有哪一些是敏感词白名单,如果遇见是需要进行展示的。通过实现 IWordAllow 接口重写 allow() 方法返回白名单敏感词。

package com.tothefor.motorcode.core.SensitiveWord;

import com.github.houbb.sensitive.word.api.IWordAllow;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
public class CustomWordAllow implements IWordAllow {

  /**
     * 允许的内容-返回的内容不被当做敏感词
     * @return
     */
  @Override
  public List<String> allow() {
    // 从数据库中查询白名单敏感词
    return Arrays.asList("五星红旗");
  }

}

自定义敏感词黑名单

增加敏感词黑名单。通过实现 IWordDeny 接口重写 deny() 方法返回黑名单敏感词。

package com.tothefor.motorcode.core.SensitiveWord;

import com.github.houbb.sensitive.word.api.IWordDeny;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * 自定义敏感词
 */
@Service
public class CustomWordDeny implements IWordDeny {

  /**
     * 拒绝出现的数据-返回的内容被当做是敏感词
     *
     * @return
     */
  @Override
  public List<String> deny() {
    // 从数据库中查询自定义敏感词
    return Arrays.asList("五星红旗");
  }

}

示例

测试自定义使用:

@Autowired
private SensitiveWordBs sensitiveWordBs;

@Test
void testWord() {
  String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
  System.out.println(sensitiveWordBs.contains(text));

  System.out.println(sensitiveWordBs.replace(text));
  System.out.println(sensitiveWordBs.replace(text, '0'));
  System.out.println(sensitiveWordBs.replace(text, new MySensitiveWordReplace()));

  System.out.println(sensitiveWordBs.findFirst(text));
  System.out.println(sensitiveWordBs.findFirst(text, WordResultHandlers.word()));
  System.out.println(sensitiveWordBs.findFirst(text, WordResultHandlers.raw()));

  System.out.println(sensitiveWordBs.findAll(text));
  System.out.println(sensitiveWordBs.findAll(text, WordResultHandlers.word()));
  System.out.println(sensitiveWordBs.findAll(text, WordResultHandlers.raw()));

}

输出:

true
五星红旗迎风飘扬,***的画像屹立在***前。 
五星红旗迎风飘扬,000的画像屹立在000前。
五星红旗迎风飘扬,教员的画像屹立在门前。 
毛主席
毛主席
WordResult{word='毛主席', startIndex=9, endIndex=12}
[毛主席, 天安门]
[毛主席, 天安门]
[WordResult{word='毛主席', startIndex=9, endIndex=12}, WordResult{word='天安门', startIndex=18, endIndex=21}]

可以看见,和之前的有一点不一样。‘五星红旗’ 并没有被过滤掉,主要原因就是因为我们的自定义敏感词白名单中加入了 ‘五星红旗’ ,所以没有被过滤掉。但是黑名单中又有这个词,为什么没有被过滤掉?这里有个点就是:如果黑名单和白名单中都有同一个敏感词,那么这个词是不会被过滤的。

重置词库

因为敏感词库的初始化较为耗时,建议程序启动时做一次 init 初始化。但为了保证敏感词修改可以实时生效且保证接口的尽可能简化,可以在数据库词库发生变更时,需要词库生效,主动触发一次初始化 sensitiveWordBs.init()。因为在调用 sensitiveWordBs.init() 的时候,根据 IWordDeny+IWordAllow 重新构建敏感词库。因为初始化可能耗时较长(秒级别),所有优化为 init 未完成时不影响旧的词库功能,完成后以新的为准

@Autowired
private SensitiveWordBs sensitiveWordBs;
sensitiveWordBs.init(); 

每次数据库的信息发生变化之后,首先调用更新数据库敏感词库的方法,然后调用这个方法。但不推荐将此方法放在数据库被修改后就调用,而推荐单独开一个接口,手动调用。

总结

  • 所有的操作均是在 SensitiveWordBs 上操作的。
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot实现敏感词过滤可以采用如下步骤: 1. 首先,需要在项目中引入敏感词库文件,可以自己编写一个敏感词库,也可以使用一些现成的敏感词库。 2. 在Spring Boot中,可以通过注解的方式实现敏感词过滤。可以使用@Aspect注解来定义切面,在切面中使用@Around注解来实现拦截功能。 3. 在拦截器中,可以通过正则表达式或者一些其他的算法来进行敏感词过滤。 4. 最后,可以将过滤后的结果返回给前端,或者直接进行处理。 下面是一个简单的实现示例: 1. 编写敏感词库文件,比如sensitive_words.txt。 2. 在项目中引入敏感词库文件,可以使用ResourceLoader来加载文件。 3. 定义切面和拦截器,实现敏感词过滤的功能。 ```java @Aspect @Component public class SensitiveFilterAspect { @Resource private ResourceLoader resourceLoader; @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public Object filterSensitiveWords(ProceedingJoinPoint pjp) throws Throwable { // 加载敏感词库文件 Resource resource = resourceLoader.getResource("classpath:sensitive_words.txt"); InputStream inputStream = resource.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); List<String> sensitiveWords = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { sensitiveWords.add(line.trim()); } // 获取请求参数 Object[] args = pjp.getArgs(); for (Object arg : args) { if (arg instanceof String) { String text = (String) arg; // 进行敏感词过滤 for (String sensitiveWord : sensitiveWords) { // 使用正则表达式进行匹配 Pattern pattern = Pattern.compile(sensitiveWord, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(text); if (matcher.find()) { // 发现敏感词,进行处理 text = text.replaceAll(sensitiveWord, "***"); } } // 替换请求参数 arg = text; } } // 继续执行请求 return pjp.proceed(args); } } ``` 4. 在Controller中使用@SensitiveFilter注解,实现敏感词过滤: ```java @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/test") @SensitiveFilter public String test(@RequestParam("text") String text) { return text; } } ``` 这样,当请求/api/test接口时,会自动进行敏感词过滤

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值