Spring Boot 实现敏感词及特殊字符过滤处理

网友投稿 425 2023-01-02

Spring Boot 实现敏感词及特殊字符过滤处理

背景:

技术采用的是 Spring Boot ,请求方法主要为 POST, 请求使用较多的注解为 @RequestBody

交付测试人员进行测试,测试人员在对模糊搜索模块进行了各种特殊字符的搜索,以至于敏感词和特殊字符均会入库。

对于我这样有情怀的开发者而言,是不能容忍的。

上来就是干!主要采用

@ControllerAdvice(basePackages = "com.my")

的方式,对用户提交的数据做处理。

以下是示例代码,不影响笔者要言表的功能实现:

/**

* @author Ryan

* @date 2019/4/25 18:41

*/

@ControllerAdvice(basePackages = "com.ytkj")

public class EscapeSensitiveWordFilter implements RequestBodyAdvice {

@Override

public boolean supports(MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

return true;

}

@Override

public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) throws IOException {

return inputMessage;

}

@Override

public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

if(o != null){

SensitiveWordUtils.apply(o);

}

return o;

}

@Override

public Objhttp://ect handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class extends HttpMessageConverter>> aClass) {

return o;

}

}

由于我们主要针对提交的数据做处理,主要入口在 SensitiveWordUtils.apply(o); 这里的 “Object ” 参数,其实也就是我们 Controller 方法参数中,打了 @RequestBody 的实体。我们可以直接在这里,使用一些手段做处理即可。

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

1. 字符串替换;

2. 自定义抛出运行时异常;

这样做的另外一个好处就是,可以在这里统一管理敏感词。

如果你使用 replaceAll 的话,统一管理上就比较费劲了EFehwC。

最后,笔者把自己写的反射放在下面,仅供参考,敏感词替换部分写了一个“测试“ 作为要替换入口的标记。

欢迎各界大佬来扶正!

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 allField = findAllField(obj);

for (Field field : allField) {

field.setAccessible(true);

Class> typeClazz = field.getType();

matchFieldType(obj, field, typeClazz);

}

}

public static List findAllField(Object object){

List 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;

}

/*EFehwC*

* @param obj

* @param field

* @param clazz

*/

public static 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> , 是不是感觉清爽了好多;

2. 过滤出来 String 类型的 Field ,其他的类型酌情考虑;

3. 等臣妾的再想想;

Spring Boot 统一敏感词过滤 demo

对象序列化前的处理

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

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

中进行对象数据的转换。

@ControllerAdvice

@Slf4j

public class ShanDongShengYuHandler implements ResponseBodyAdvice {

@Autowired

private ObjectMapper objectMapper;

@Override

public boolean supports(MethodParameter returnType, Class converterType) {

return true;

}

@Override

public 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();

}

}

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:外部api接口对接到网站(网站api接口怎么对接)
下一篇:义乌优速快递物流查询单号(义乌优速快递服务电话)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~