分享一個敏感詞過濾方法數組
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