敏感詞過濾

分享一個敏感詞過濾方法數組

 1     public class WordFilterController : BaseController  2  {  3         /// <summary>  
 4         /// 敏感字數組  5         /// </summary>  
 6         public static string[] s_filters = null;  7 
 8         /// <summary>  
 9         /// 初始化s_filters以後調用filter函數  10         /// </summary>  
 11         /// <param name="content">欲過濾的內容</param>  
 12         /// <param name="result_str">執行過濾以後的內容</param>  
 13         /// <param name="filter_deep">檢測深度,即s_filters數組中的每一個詞中的插入幾個字之內會被過濾掉,例:檢測深度爲2,s_filters中有個詞是中國,那麼「中國」、「中*國」,「中**國」都會被過濾掉(*是任意字)。</param>  
 14         /// <param name="check_only">是否只檢測而不執行過濾操做</param>  
 15         /// <param name="bTrim">過濾以前是否要去掉頭尾的空字符</param>  
 16         /// <param name="replace_str">將檢測到的敏感字替換成的字符</param>  
 17         /// <returns></returns>  
 18         public static bool Filter(string content, out string result_str, int filter_deep = 1, bool check_only = false, bool bTrim = false, string replace_str = "*")  19  {  20             string result = content;  21             if (bTrim)  22  {  23                 result = result.Trim();  24  }  25             result_str = result;  26 
 27             if (s_filters == null)  28  {  29                 return false;  30  }  31 
 32             bool check = false;  33             foreach (string str in s_filters)  34  {  35                 string s = str.Replace(replace_str, "");  36                 if (s.Length == 0)  37  {  38                     continue;  39  }  40 
 41                 bool bFiltered = true;  42                 while (bFiltered)  43  {  44                     int result_index_start = -1;  45                     int result_index_end = -1;  46                     int idx = 0;  47                     while (idx < s.Length)  48  {  49                         string one_s = s.Substring(idx, 1);  50                         if (one_s == replace_str)  51  {  52                             continue;  53  }  54                         if (result_index_end + 1 >= result.Length)  55  {  56                             bFiltered = false;  57                             break;  58  }  59                         int new_index = result.IndexOf(one_s, result_index_end + 1, StringComparison.OrdinalIgnoreCase);  60                         if (new_index == -1)  61  {  62                             bFiltered = false;  63                             break;  64  }  65                         if (idx > 0 && new_index - result_index_end > filter_deep + 1)  66  {  67                             bFiltered = false;  68                             break;  69  }  70                         result_index_end = new_index;  71 
 72                         if (result_index_start == -1)  73  {  74                             result_index_start = new_index;  75  }  76                         idx++;  77  }  78 
 79                     if (bFiltered)  80  {  81                         if (check_only)  82  {  83                             return true;  84  }  85                         check = true;  86                         string result_left = result.Substring(0, result_index_start);  87                         for (int i = result_index_start; i <= result_index_end; i++)  88  {  89                             result_left += replace_str;  90  }  91                         string result_right = result.Substring(result_index_end + 1);  92                         result = result_left + result_right;  93  }  94  }  95  }  96             result_str = result;  97             return check;  98  }  99 
100     }

我用的是MVC框架,直接重寫DefaultModelBinder裏面的BindModel方法框架

 1     public class FilterModelBinder : DefaultModelBinder  2  {  3         public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)  4  {  5             var value = base.BindModel(controllerContext, bindingContext);  6             if (bindingContext.ModelType == typeof(string))  7  {  8                 string return_value = string.Empty;  9                 WordFilterController.s_filters = new AppDbContext().WordFilters.Select(x => x.Word).ToArray(); 10                 var flag =  WordFilterController.Filter(value as string,out return_value); 11                 if (flag) 12  { 13                     return return_value; 14  } 15  } 16             return value; 17  } 18     }

在網上還查到另外一種重寫IModelBinder的方法也能夠實現,這邊就不記錄了ide

最後Global.asax在Application_Start()方法中加上函數

ModelBinders.Binders.DefaultBinder = new FilterModelBinder();

搞定~測試

 

【2018.04.09】更新spa

在後續項目測試中發現,這樣給所有的model都綁上敏感詞過濾有些蠢。主要是1.開發敏感詞管理模塊時,會本身把本身和諧了2.一些敏感詞是數字或字符可能會和GUID衝突致使值傳遞出現BUGcode

因此稍微改了下,只針對部分entity進行過濾,而且排除IDblog

這是新的ModelBinder,此次只重寫SetProperty方法ip

 1     public class WordFilterModelBinder : DefaultModelBinder  2  {  3         protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)  4  {  5             if (propertyDescriptor.PropertyType == typeof(string) && propertyDescriptor.Name.ToLowerInvariant() != "id")  6  {  7                 WordFilterService.s_filters = (from x in new LibraryContext().WordFilters select x.Word).ToArray<string>();  8                 var stringValue = (string)value;  9                 bool flag = WordFilterService.filter(value as string, out stringValue, 1, false, false, "*"); 10                 if (flag) 11  { 12                     value = stringValue; 13  } 14  } 15             base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value); 16  } 17     }

而後一樣修改Global.asax的Application_Start()方法開發

1             //ModelBinders.Binders.DefaultBinder = new SSOCT.Library.CustomModelBinder();
2             ModelBinders.Binders.Add(typeof(DAL.Models.Activity), new WordFilterModelBinder()); 3             ModelBinders.Binders.Add(typeof(DAL.Models.Comment), new WordFilterModelBinder());

這樣就能夠針對性的進行過濾了,可是過濾層級只到Entity,不能精確到只針對某個字段

可能有更好的辦法,如今想是用Attribute應該能夠實現針對字段過濾,等後續再更新……

 

 

另外,敏感詞庫我也找了個比較全【2017版】的,直接發在這邊了(直接複製連接下載):

https://files.cnblogs.com/files/cn2018/mgck2017.rar

相關文章
相關標籤/搜索