翼度科技»论坛 编程开发 .net 查看内容

.NET 6 实现敏感词过滤

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
一、什么是敏感词过滤?

敏感词过滤是一种处理网络内容的技术,可以检测和过滤出网络中的敏感/违禁词汇。它通过给定的关键字或字符串,判断网络内容是否包含某些敏感信息,从而防止违反法律法规的信息流通。
通常,可以使用两种方法来过滤敏感词:

  • 黑名单过滤:即定义一个黑名单,将所有敏感词择记录在其中,然后对输入的文本进行对比,如果发现有敏感词,就将其过滤掉。
  • 白名单过滤:即定义一个白名单,将所有不敏感的词汇记录在其中,然后对输入的文本进行对比,如果发现有不在白名单中的词汇,就将其过滤掉。
二、ToolGood.Words是什么?

ToolGood.Words是一款高性能非法词(敏感词)检测组件,附带繁体简体互换,支持全角半角互换,获取拼音首字母,获取拼音字母,拼音模糊搜索等功能。
ToolGood.Words的源码网站:ToolGood.Words源码网站
三、在Visual Studio中安装ToolGood.Words

3.1、右键项目解决方案,选择“管理NuGet程序包”,如下图所示:


3.2、切换到“浏览”选项卡,搜索“ToolGood.Words”并安装:


安装完之后最好重新编译生成项目
四、创建“subContentCheck”类

敏感/违禁词汇因特殊内容不便上传,可自行在网站上查找
  1. using Microsoft.AspNetCore.DataProtection.KeyManagement;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.CodeAnalysis.Text;
  4. using Newtonsoft.Json;
  5. using System.Collections;
  6. using System.Text;
  7. using ToolGood.Words;
  8. using static System.Net.Mime.MediaTypeNames;
  9. using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
  10. namespace WebApplication1 //放在自己项目中时,需要更换为自己的命名空间
  11. {
  12.     public class keywords
  13.     {
  14.         public List<string> IllegalKeywords { get; set; }
  15.     }
  16.     public class urlwords
  17.     {
  18.         public List<string> IllegalUrls { get; set; }
  19.     }
  20.     /// <summary>
  21.     /// 提交的内容敏感违禁词检查类
  22.     /// </summary>
  23.     public class subContentCheck
  24.     {
  25.         /// <summary>
  26.         /// 本地静态文件地址路径
  27.         /// </summary>
  28.         private IHostingEnvironment _hostingEnv;
  29.         /// <summary>
  30.         /// 敏感词库
  31.         /// </summary>
  32.         private string dictionaryPath = "/sensitiveWords/sensitiveWords.txt";
  33.         /// <summary>
  34.         /// 敏感链接、网站、网址库
  35.         /// </summary>
  36.         private string urlsPath = "/sensitiveWords/IllegalUrls.txt";
  37.         /// <summary>
  38.         /// 保存敏感词组
  39.         /// </summary>
  40.         public string[] Words { get; set; }
  41.         /// <summary>
  42.         /// 一个参数的构造函数
  43.         /// </summary>
  44.         /// <param name="hostingEnv">本地静态文件地址路径</param>
  45.         public subContentCheck(IHostingEnvironment hostingEnv)
  46.         {
  47.             _hostingEnv = hostingEnv;
  48.             InitDictionary();
  49.         }
  50.         /// <summary>
  51.         /// 初始化内存敏感词库
  52.         /// </summary>
  53.         public void InitDictionary()
  54.         {
  55.             Words = new string[] { };
  56.             string wordsPath = _hostingEnv.WebRootPath + dictionaryPath;
  57.             string urlPath = _hostingEnv.WebRootPath + urlsPath;
  58.             //List<keywords> keys = new List<keywords>();
  59.             //List<urlwords> urls = new List<urlwords>();
  60.             string[] readAllWords = System.IO.File.ReadAllLines(wordsPath, System.Text.Encoding.UTF8);
  61.             string[] readAllurl = System.IO.File.ReadAllLines(urlPath, System.Text.Encoding.UTF8);
  62.             //由于数组是非动态的,不能进行动态的添加,所有先将它转成list,操作
  63.             ArrayList arrayList = new ArrayList(Words.ToList());
  64.             if (readAllWords.Length > 0 || readAllurl.Length > 0)
  65.             {
  66.                 if (readAllWords.Length > 1)
  67.                 {
  68.                     //keywords key = new keywords();
  69.                     //key.IllegalKeywords = new List<string>();
  70.                     foreach (string itemWords in readAllWords)
  71.                     {
  72.                         string[] allSplitWords = itemWords.Split('|');
  73.                         foreach (string itemSplitWords in allSplitWords)
  74.                         {
  75.                             if (!string.IsNullOrEmpty(itemSplitWords))
  76.                             {
  77.                                 arrayList.Add(itemSplitWords);
  78.                                 //string aaa = itemSplitWords;
  79.                                 //key.IllegalKeywords.Add(aaa);
  80.                                 //IllegalKeywords.Add(itemSplitWords);
  81.                             }
  82.                         }
  83.                     }
  84.                     //keys.Add(key);
  85.                 }
  86.                 else
  87.                 {
  88.                     if (readAllWords.Length == 1)
  89.                     {
  90.                         string[] allSplitWords = readAllWords[0].Split('|');
  91.                         //keywords key = new keywords();
  92.                         //key.IllegalKeywords = new List<string>();
  93.                         foreach (string itemSplitWords in allSplitWords)
  94.                         {
  95.                             if (!string.IsNullOrEmpty(itemSplitWords))
  96.                             {
  97.                                 arrayList.Add(itemSplitWords);
  98.                                 //string aaa = itemSplitWords;
  99.                                 //key.IllegalKeywords.Add(aaa);
  100.                                 //IllegalKeywords.Add(itemSplitWords);
  101.                             }
  102.                         }
  103.                         //keys.Add(key);
  104.                     }
  105.                 }
  106.                 if (readAllurl.Length > 1)
  107.                 {
  108.                     //urlwords url = new urlwords();
  109.                     //url.IllegalUrls = new List<string>();
  110.                     foreach (string itemUrls in readAllurl)
  111.                     {
  112.                         string[] allSplitUrls = itemUrls.Split('|');
  113.                         foreach (string itemSplitUrls in allSplitUrls)
  114.                         {
  115.                             if (!string.IsNullOrEmpty(itemSplitUrls))
  116.                             {
  117.                                 arrayList.Add(itemSplitUrls);
  118.                                 //string Keyword = itemSplitUrls;
  119.                                 //url.IllegalUrls.Add(Keyword);
  120.                                 //IllegalUrls.Add(itemSplitUrls);
  121.                             }
  122.                         }
  123.                     }
  124.                     //urls.Add(url);
  125.                 }
  126.                 else
  127.                 {
  128.                     if (readAllurl.Length == 1)
  129.                     {
  130.                         string[] allSplitUrls = readAllurl[0].Split('|');
  131.                         //urlwords url = new urlwords();
  132.                         //url.IllegalUrls = new List<string>();
  133.                         foreach (string itemSplitUrls in allSplitUrls)
  134.                         {
  135.                             if (!string.IsNullOrEmpty(itemSplitUrls))
  136.                             {
  137.                                 arrayList.Add(itemSplitUrls);
  138.                                 //IllegalUrls.Add(itemSplitUrls);
  139.                                 //string Keyword = itemSplitUrls;
  140.                                 //url.IllegalUrls.Add(Keyword);
  141.                             }
  142.                         }
  143.                         //urls.Add(url);
  144.                     }
  145.                 }
  146.             }
  147.             //我们在将list转换成String[]数组
  148.             Words = (string[])arrayList.ToArray(typeof(string));
  149.         }
  150.         /// <summary>
  151.         /// 过滤替换敏感词
  152.         /// </summary>
  153.         /// <param name="sourceText">需要过滤替换的原内容</param>
  154.         /// <param name="replaceChar">敏感词替换的字符;默认替换为‘*’</param>
  155.         /// <returns>返回状态码;为空则表示传入的内容为空;“0”:设置违禁词时发生错误;“1”:敏感内容替换时发生错误;“2”:需要替换的文本内容为空;其余则返回替换成功的字符串内容</returns>
  156.         public string FilterWithChar(string sourceText, char replaceChar = '*')
  157.         {
  158.             if (!string.IsNullOrEmpty(sourceText))
  159.             {
  160.                 string result = "";
  161.                 WordsSearch wordsSearch = new WordsSearch();
  162.                 try
  163.                 {
  164.                     wordsSearch.SetKeywords(Words);
  165.                 }
  166.                 catch (Exception ex)
  167.                 {
  168.                     result = "0";
  169.                     return result;
  170.                 }
  171.                 try
  172.                 {
  173.                     result = wordsSearch.Replace(sourceText, replaceChar);
  174.                     return result;
  175.                 }
  176.                 catch (Exception ex)
  177.                 {
  178.                     return result = "1";
  179.                 }
  180.             }
  181.             else
  182.             {
  183.                 return "2";
  184.             }
  185.         }
  186.         /// <summary>
  187.         /// 查找原内容中知否包含敏感/违禁词
  188.         /// </summary>
  189.         /// <param name="sourceText">需要判断的原内容</param>
  190.         /// <returns>返回状态码;为空则表示传入的内容为空;“0”:设置违禁词时发生错误;“1”:敏感内容查询时发生错误;“2”:需要替换的文本内容为空;“3”:原内容中包含敏感/违禁词汇;“4”:原内容中不包含敏感/违禁词汇</returns>
  191.         public string FindSensitiveKey(string sourceText)
  192.         {
  193.             string result = "";
  194.             if (!string.IsNullOrEmpty(sourceText))
  195.             {
  196.                 WordsSearch wordsSearch = new WordsSearch();
  197.                 try
  198.                 {
  199.                     wordsSearch.SetKeywords(Words);
  200.                 }
  201.                 catch (Exception ex)
  202.                 {
  203.                     result = "0";
  204.                     return result;
  205.                 }
  206.                 try
  207.                 {
  208.                     bool res = wordsSearch.ContainsAny(sourceText);
  209.                     if (res)
  210.                     {
  211.                         result = "3";
  212.                         return result;
  213.                     }
  214.                     else
  215.                     {
  216.                         result = "4";
  217.                         return result;
  218.                     }
  219.                 }
  220.                 catch (Exception ex)
  221.                 {
  222.                     return result = "1";
  223.                 }
  224.             }
  225.             else
  226.             {
  227.                 result = "2";
  228.             }
  229.             return result;
  230.         }
  231.         /// <summary>
  232.         /// 把对象写入到json文件中
  233.         /// </summary>
  234.         /// <param name="obj"></param>
  235.         /// <returns></returns>
  236.         public static void Write(List<keywords> jsonData, List<urlwords> urlJsonData, string filename)
  237.         {
  238.             var directorypath = Directory.GetCurrentDirectory();
  239.             string strFileName = directorypath + "\" + filename + ".json";
  240.             string ListJson = "";
  241.             if (jsonData != null)
  242.             {
  243.                 ListJson = JsonConvert.SerializeObject(jsonData);
  244.             }
  245.             else
  246.             {
  247.                 ListJson = JsonConvert.SerializeObject(urlJsonData);
  248.             }
  249.             Console.WriteLine(ListJson);
  250.             writeJsonFile(strFileName, ListJson);
  251.             //将序列化的json字符串内容写入Json文件,并且保存
  252.             void writeJsonFile(string path, string jsonConents)
  253.             {
  254.                 using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, FileShare.ReadWrite))
  255.                 {
  256.                     //如果json文件中有中文数据,可能会出现乱码的现象,那么需要加上如下代码
  257.                     Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  258.                     using (StreamWriter sw = new StreamWriter(fs, Encoding.GetEncoding("GB2312")))
  259.                     {
  260.                         sw.WriteLine(jsonConents);
  261.                     }
  262.                 }
  263.             }
  264.         }
  265.     }
  266. }
复制代码
五、写API接口
  1. /// <summary>
  2. /// 进行敏感词脱敏
  3. /// </summary>
  4. /// <param name="sourctText">需要脱敏的文本内容</param>
  5. /// <returns></returns>
  6. [HttpPost]
  7. public IActionResult sensitive_words_replace2(string sourctText)
  8. {
  9.     string resultStr = "";
  10.     //实例化敏感词库
  11.     subContentCheck strCheck = new subContentCheck(_hostingEnv);
  12.     if (string.IsNullOrEmpty(sourctText))
  13.     {
  14.         return Json(new { code = 230, msg = "需要替换的文本内容为空!", resultStr = resultStr });
  15.     }
  16.     try
  17.     {
  18.         resultStr = strCheck.FilterWithChar(sourctText);
  19.         string resMsg = "";
  20.         int resCode = 200;
  21.         if (resultStr=="0")
  22.         {
  23.             resCode = 210;
  24.             resultStr = "";
  25.             resMsg = "设置违禁词时发生错误,请联系管理员!";
  26.         }else if (resultStr=="1")
  27.         {
  28.             resCode = 240;
  29.             resultStr = "";
  30.             resMsg = "敏感内容替换时发生错误!";
  31.         }
  32.         else if (resultStr == "2")
  33.         {
  34.             resCode = 260;
  35.             resultStr = "";
  36.             resMsg = "需要替换的文本内容为空!";
  37.         }
  38.         else
  39.         {
  40.             resCode = 200;
  41.             resMsg = "敏感词替换请求成功!";
  42.         }
  43.         return Json(new { code = resCode, msg = resMsg, resultStr = resultStr });
  44.     }
  45.     catch (Exception ex)
  46.     {
  47.         return Json(new { code = 220, msg = "敏感内容替换时发生错误!", resultStr = "" });
  48.     }
  49. }
  50. /// <summary>
  51. /// 进行敏感词判断
  52. /// </summary>
  53. /// <param name="sourctText">需要脱敏的文本内容</param>
  54. /// <returns></returns>
  55. [HttpPost]
  56. public IActionResult whether_sensitive_words(string sourctText)
  57. {
  58.     string resultStr = "";
  59.     //实例化敏感词库
  60.     subContentCheck strCheck = new subContentCheck(_hostingEnv);
  61.     if (string.IsNullOrEmpty(sourctText))
  62.     {
  63.         return Json(new { code = 230, msg = "需要替换的文本内容为空!", resultStr = resultStr });
  64.     }
  65.     try
  66.     {
  67.         resultStr = strCheck.FindSensitiveKey(sourctText);
  68.         string resMsg = "";
  69.         int resCode = 200;
  70.         if (resultStr == "0")
  71.         {
  72.             resCode = 210;
  73.             resultStr = "";
  74.             resMsg = "设置违禁词时发生错误,请联系管理员!";
  75.         }
  76.         else if (resultStr == "1")
  77.         {
  78.             resCode = 240;
  79.             resultStr = "";
  80.             resMsg = "敏感内容匹配时发生错误!";
  81.         }
  82.         else if (resultStr == "2")
  83.         {
  84.             resCode = 260;
  85.             resultStr = "";
  86.             resMsg = "需要判断的文本内容为空!";
  87.         }
  88.         else if (resultStr == "3")
  89.         {
  90.             resCode = 270;
  91.             resultStr = "";
  92.             resMsg = "内容中含有敏感/违禁词!";
  93.         }
  94.         else
  95.         {
  96.             resCode = 200;
  97.             resMsg = "内容中不含敏感/违禁词!";
  98.         }
  99.         return Json(new { code = resCode, msg = resMsg, resultStr = resultStr });
  100.     }
  101.     catch (Exception ex)
  102.     {
  103.         return Json(new { code = 220, msg = "敏感内容匹配时发生错误!", resultStr = "" });
  104.     }
  105. }
复制代码
六、前端封装JS方法
  1. /**
  2. * 敏感词/违禁词替换
  3. * @param {string} sourctText 需要进行替换的内容
  4. * @param {string} boxid 将替换成功之后的内容赋值的元素容器id属性名
  5. * @param {object} layui Layui实例
  6. * @returns 替换之后的文本内容
  7. */
  8. function sensitive_words_replace(sourctText, boxid, layui) {
  9.     let resultStr = "";
  10.     //let url = ["/Home/sensitive_words_replace", "/Home/sensitive_words_replace1", "/Home/sensitive_words_replace2"];
  11.     $.ajax({
  12.         url: "/Home/sensitive_words_replace2",//请求后端接口的路径
  13.         dataType: "JSON",
  14.         type: "POST",
  15.         data: {
  16.             "sourctText": sourctText
  17.         },
  18.         success: function (res) {
  19.             let resCode = res.code;
  20.             let resMsg = res.msg;
  21.             if ((resCode == "210" || resCode == 210) || (resCode == 220 || resCode == "220") || (resCode == 230 || resCode == "230") || (resCode == 240 || resCode == "240") || (resCode == 260 || resCode == "260")) {
  22.                 //返回数据后关闭loading
  23.                 layer.closeAll();
  24.                 resultStr = res.resultStr;
  25.                 layui.layer.alert(resMsg, { icon: 5, title: "温馨提示", closeBtn: 0 });
  26.             } else if (resCode == 200 || resCode == "200") {
  27.                 resultStr = res.resultStr;
  28.                 $("#" + boxid).val(resultStr);
  29.                 //返回数据后关闭loading
  30.                 layer.closeAll();
  31.             }
  32.         },
  33.         error: function (error) {
  34.             //返回数据后关闭loading
  35.             layer.closeAll();
  36.             layui.layer.alert(error, { icon: 5, title: "温馨提示", closeBtn: 0 });
  37.         }
  38.     });
  39.     return resultStr;
  40. }
  41. /**
  42. * 查询是否包含敏感/违禁词
  43. * @param {string} sourctText 需要进行替换的内容
  44. * @param {string} boxid 将替换成功之后的内容赋值的元素容器id属性名
  45. * @param {object} layui Layui实例
  46. * @returns 返回Bool;包含:“true”;不包含:“false”
  47. */
  48. function whether_sensitive_words(sourctText, boxid, layui) {
  49.     let resultBool = false;
  50.     $.ajax({
  51.         url: "/Home/whether_sensitive_words",//请求后端接口的路径
  52.         dataType: "JSON",
  53.         type: "POST",
  54.         async: false,//此处需要注意的是要想获取ajax返回的值这个async属性必须设置成同步的,否则获取不到返回值
  55.         data: {
  56.             "sourctText": sourctText
  57.         },
  58.         success: function (res) {
  59.             let resCode = res.code;
  60.             let resMsg = res.msg;
  61.             if ((resCode == "210" || resCode == 210) || (resCode == 220 || resCode == "220") || (resCode == 230 || resCode == "230") || (resCode == 240 || resCode == "240") || (resCode == 260 || resCode == "260")) {
  62.                 resultBool = false;
  63.                 layui.layer.alert(resMsg, { icon: 5, title: "温馨提示", closeBtn: 0 });
  64.             } else if (resCode == 270 || resCode == "270") {
  65.                 resultBool = true;
  66.             } else if (resCode == 200 || resCode == "200") {
  67.                 resultBool = false;
  68.                 //返回数据后关闭loading
  69.                 layer.closeAll();
  70.             }
  71.         },
  72.         error: function (error) {
  73.             layui.layer.alert(error, { icon: 5, title: "温馨提示", closeBtn: 0 });
  74.         }
  75.     });
  76.     return resultBool;
  77. }
复制代码
来源:https://www.cnblogs.com/lucasDC/archive/2023/03/25/17255906.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具