本篇内容介绍了“Springboot敏感词过滤及特殊字符过滤的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
技术采用的是 SpringBoot ,请求方法主要为 POST,交付测试人员进行测试,测试人员在对模糊搜索模块进行了各种特殊字符的搜索,以至于敏感词和特殊字符均会入库,那么 springboot 敏感词过滤及特殊字符过滤处理要如何实现呢?
@ControllerAdvice(basePackages = "com.my")
的方式,对用户提交的数据做处理。
/*** @author Ryan* @date 2019/4/25 18:41*/@ControllerAdvice(basePackages = "com.ytkj")public class EscapeSensitiveWordFilter implements RequestBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return true;}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {return inputMessage;}@Overridepublic Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {if(o != null){SensitiveWordUtils.apply(o);}return o;}@Overridepublic Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return o;}}
由于我们主要针对提交的数据做处理,主要入口在 SensitiveWordUtils.apply(o); 这里的 “Object ” 参数,其实也就是我们 Controller 方法参数中,打了 @RequestBody 的实体。我们可以直接在这里,使用一些手段做处理即可。
这里的手段,也只能使用反射了(如果读者有什么好的方案可以告诉我)。
1. 字符串替换;
2. 自定义抛出运行时异常;
这样做的另外一个好处就是,可以在这里统一管理敏感词。
如果你使用 replaceAll 的话,统一管理上就比较费劲了。
最后,笔者把自己写的反射放在下面,仅供参考,敏感词替换部分写了一个“测试“ 作为要替换入口的标记。
欢迎各界大佬来扶正!
import java.lang.reflect.Field;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Map;/*** @author Ryan* @date 2019/4/26 12:40*/public class SensitiveWordUtils {/*** @param result* @return*/public static Object apply(Object result) {if (result == null) {return null;}objectParse(result);return result;}/*** @param obj*/public static void objectParse(Object obj) {List<Field> allField = findAllField(obj);for (Field field : allField) {field.setAccessible(true);Class<?> typeClazz = field.getType();matchFieldType(obj, field, typeClazz);}}public static List<Field> findAllField(Object object){List<Field> result = new ArrayList<>();Class<?> clazz = object.getClass();while (true) {clazz = clazz.getSuperclass();if (clazz == Object.class) {break;}Field[] declaredFields = clazz.getDeclaredFields();result.addAll(Arrays.asList(declaredFields));}return result;}/*** @param obj* @param field* @param clazz*/public static <T> void matchFieldType(Object obj, Field field, T clazz) {try {T param = (T) field.get(obj);if(param == null){return;}if (clazz == List.class) {List p = (List)param;for (Object o : p) {objectParse(o);}} else if (clazz == String.class) {setValue(obj, field, "测试");} else if (clazz == Map.class) {Map map = (Map)param;for (Object o : map.keySet()) {objectParse(o);}}} catch (IllegalAccessException e) {e.printStackTrace();}}/**** @param object* @param field* @param param* @throws IllegalAccessException*/public static void setValue(Object object, Field field, Object param) throws IllegalAccessException {if(!field.isAccessible()){throw new IllegalAccessException("modify the field fail.");}field.set(object, param);}}
这里的 SensitiveWordUtils 还有很大的优化点,我在这里没有目前只是看看效果,写的很粗糙,望大神不要喷。
1. 缓存 object 的 String.class 类型的 Field 或者 methodName; 在第一次加载的时候,缓存进去;放到 ConcurrentHashMap<ObjectType, List<StringField>> , 是不是感觉清爽了好多;
2. 过滤出来 String 类型的 Field ,其他的类型酌情考虑;
3. 等臣妾的再想想;
对象序列化前的处理
例如springframework框架(responseBody)json 格式:
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain#beforeBodyWrite
中进行对象数据的转换。
@ControllerAdvice@Slf4jpublic class ShanDongShengYuHandler implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;} @Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {ResponseData d = new ResponseData();sensitiveHidden(body);d.setData(body);return d;} /*** 只支持自定义类型数据的敏感词过滤,考虑递归性能*/private void sensitiveHidden(Object body) {if(body==null || StringUtils.isBlank(body.getClass().getName()) || !body.getClass().getName().contains("山东")){return;}Field[] declaredFields = body.getClass().getDeclaredFields();for (Field declaredField : declaredFields) {SensitiveWorldHidden annotation = declaredField.getAnnotation(SensitiveWorldHidden.class);log.warn("【注解类型】{}",annotation);try {declaredField.setAccessible(true);Object o = declaredField.get(body);if(annotation != null) {String content = objectMapper.writeValueAsString(o);content = content.replace("垃圾", "**");Object replaced = objectMapper.readValue(content, o.getClass());declaredField.set(body, replaced);}else {sensitiveHidden(o);}} catch (IllegalAccessException e) {e.printStackTrace();} catch (JsonProcessingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}}
“Springboot敏感词过滤及特殊字符过滤的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。