App下載

Springboot敏感詞過濾及特殊字符過濾處理

猿友 2021-06-29 15:40:11 瀏覽數(shù) (7619)
反饋

技術(shù)采用的是 SpringBoot ,請求方法主要為 POST,交付測試人員進(jìn)行測試,測試人員在對模糊搜索模塊進(jìn)行了各種特殊字符的搜索,以至于敏感詞和特殊字符均會入庫,那么 springboot 敏感詞過濾及特殊字符過濾處理要如何實(shí)現(xiàn)呢?

  1. @ControllerAdvice(basePackages = "com.my")

的方式,對用戶提交的數(shù)據(jù)做處理。

以下是示例代碼,不影響筆者要言表的功能實(shí)現(xiàn):

  1. /**
  2. * @author Ryan
  3. * @date 2019/4/25 18:41
  4. */
  5. @ControllerAdvice(basePackages = "com.ytkj")
  6. public class EscapeSensitiveWordFilter implements RequestBodyAdvice {
  7. @Override
  8. public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
  9. return true;
  10. }
  11. @Override
  12. public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
  13. return inputMessage;
  14. }
  15. @Override
  16. public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
  17. if(o != null){
  18. SensitiveWordUtils.apply(o);
  19. }
  20. return o;
  21. }
  22. @Override
  23. public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
  24. return o;
  25. }
  26. }

由于我們主要針對提交的數(shù)據(jù)做處理,主要入口在 SensitiveWordUtils.apply(o); 這里的 “Object ” 參數(shù),其實(shí)也就是我們 Controller 方法參數(shù)中,打了 @RequestBody 的實(shí)體。我們可以直接在這里,使用一些手段做處理即可。

這里的手段,也只能使用反射了(如果讀者有什么好的方案可以告訴我)。

1. 字符串替換;

2. 自定義拋出運(yùn)行時異常;

這樣做的另外一個好處就是,可以在這里統(tǒng)一管理敏感詞。

如果你使用 replaceAll 的話,統(tǒng)一管理上就比較費(fèi)勁了。

最后,筆者把自己寫的反射放在下面,僅供參考,敏感詞替換部分寫了一個“測試“ 作為要替換入口的標(biāo)記。

歡迎各界大佬來扶正!

  1. import java.lang.reflect.Field;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.List;
  5. import java.util.Map;
  6. /**
  7. * @author Ryan
  8. * @date 2019/4/26 12:40
  9. */
  10. public class SensitiveWordUtils {
  11. /**
  12. * @param result
  13. * @return
  14. */
  15. public static Object apply(Object result) {
  16. if (result == null) {
  17. return null;
  18. }
  19. objectParse(result);
  20. return result;
  21. }
  22. /**
  23. * @param obj
  24. */
  25. public static void objectParse(Object obj) {
  26. List<Field> allField = findAllField(obj);
  27. for (Field field : allField) {
  28. field.setAccessible(true);
  29. Class<?> typeClazz = field.getType();
  30. matchFieldType(obj, field, typeClazz);
  31. }
  32. }
  33. public static List<Field> findAllField(Object object){
  34. List<Field> result = new ArrayList<>();
  35. Class<?> clazz = object.getClass();
  36. while (true) {
  37. clazz = clazz.getSuperclass();
  38. if (clazz == Object.class) {
  39. break;
  40. }
  41. Field[] declaredFields = clazz.getDeclaredFields();
  42. result.addAll(Arrays.asList(declaredFields));
  43. }
  44. return result;
  45. }
  46. /**
  47. * @param obj
  48. * @param field
  49. * @param clazz
  50. */
  51. public static <T> void matchFieldType(Object obj, Field field, T clazz) {
  52. try {
  53. T param = (T) field.get(obj);
  54. if(param == null){
  55. return;
  56. }
  57. if (clazz == List.class) {
  58. List p = (List)param;
  59. for (Object o : p) {
  60. objectParse(o);
  61. }
  62. } else if (clazz == String.class) {
  63. setValue(obj, field, "測試");
  64. } else if (clazz == Map.class) {
  65. Map map = (Map)param;
  66. for (Object o : map.keySet()) {
  67. objectParse(o);
  68. }
  69. }
  70. } catch (IllegalAccessException e) {
  71. e.printStackTrace();
  72. }
  73. }
  74. /**
  75. *
  76. * @param object
  77. * @param field
  78. * @param param
  79. * @throws IllegalAccessException
  80. */
  81. public static void setValue(Object object, Field field, Object param) throws IllegalAccessException {
  82. if(!field.isAccessible()){
  83. throw new IllegalAccessException("modify the field fail.");
  84. }
  85. field.set(object, param);
  86. }
  87. }

這里的 SensitiveWordUtils 還有很大的優(yōu)化點(diǎn),我在這里沒有目前只是看看效果,寫的很粗糙,望大神不要噴。

讀者自行實(shí)現(xiàn)一下,我說一下優(yōu)化點(diǎn):

1. 緩存 object 的 String.class 類型的 Field 或者 methodName; 在第一次加載的時候,緩存進(jìn)去;放到 ConcurrentHashMap<ObjectType, List<StringField>> , 是不是感覺清爽了好多;

2. 過濾出來 String 類型的 Field ,其他的類型酌情考慮;

3. 等臣妾的再想想;

Spring Boot 統(tǒng)一敏感詞過濾 demo

對象序列化前的處理

例如springframework框架(responseBody)json 格式:

  1. org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain#beforeBodyWrite

中進(jìn)行對象數(shù)據(jù)的轉(zhuǎn)換。

  1. @ControllerAdvice
  2. @Slf4j
  3. public class ShanDongShengYuHandler implements ResponseBodyAdvice {
  4. @Autowired
  5. private ObjectMapper objectMapper;
  6. @Override
  7. public boolean supports(MethodParameter returnType, Class converterType) {
  8. return true;
  9. }
  10.  
  11. @Override
  12. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  13. ResponseData d = new ResponseData();
  14. sensitiveHidden(body);
  15. d.setData(body);
  16. return d;
  17. }
  18.  
  19. /**
  20. * 只支持自定義類型數(shù)據(jù)的敏感詞過濾,考慮遞歸性能
  21. */
  22. private void sensitiveHidden(Object body) {
  23. if(body==null || StringUtils.isBlank(body.getClass().getName()) || !body.getClass().getName().contains("山東")){
  24. return;
  25. }
  26. Field[] declaredFields = body.getClass().getDeclaredFields();
  27. for (Field declaredField : declaredFields) {
  28. SensitiveWorldHidden annotation = declaredField.getAnnotation(SensitiveWorldHidden.class);
  29. log.warn("【注解類型】{}",annotation);
  30. try {
  31. declaredField.setAccessible(true);
  32. Object o = declaredField.get(body);
  33. if(annotation != null) {
  34. String content = objectMapper.writeValueAsString(o);
  35. content = content.replace("垃圾", "**");
  36. Object replaced = objectMapper.readValue(content, o.getClass());
  37. declaredField.set(body, replaced);
  38. }else {
  39. sensitiveHidden(o);
  40. }
  41. } catch (IllegalAccessException e) {
  42. e.printStackTrace();
  43. } catch (JsonProcessingException e) {
  44. e.printStackTrace();
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. }
  50. }

 springboot 敏感詞過濾及特殊字符過濾處理要如何實(shí)現(xiàn)就位大家分享到這里了。


0 人點(diǎn)贊