使用RequestBodyAdvice实现对Http请求非法字符过滤

RequestBodyAdvice对Http请求非法字符过滤 利用RequestBodyAdvice对HTTP请求参数放入body中的参数进行非法字符过滤。
要求:spring 4.2+
额外的pom.xml

org.apache.commonscommons-io1.3.2 com.alibabafastjson1.2.44

【使用RequestBodyAdvice实现对Http请求非法字符过滤】代码
package com.niugang.controller; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; /** * RequestBodyAdvice:解释 * 允许在将请求的主体读取和转换成一个对象之前对请求进行自定义, * 并允许在将其传递到控制器方法作为一个@RequestBody或HttpEntity方法参数之前处理结果对象。 * * @author niugang * */@ControllerAdvice(basePackages = "com.niugang")public class MyRequestBodyAdvice implements RequestBodyAdvice {private final static Logger logger = LoggerFactory.getLogger(MyRequestBodyAdvice.class); @Overridepublic boolean supports(MethodParameter methodParameter, Type targetType,Class> converterType) {return true; }@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class> converterType) {return body; } @Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class> converterType) throws IOException {try {return new MyHttpInputMessage(inputMessage); } catch (Exception e) {e.printStackTrace(); return inputMessage; }}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class> converterType) {return body; } class MyHttpInputMessage implements HttpInputMessage {private HttpHeaders headers; private InputStream body; @SuppressWarnings("unchecked")public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {String string = IOUtils.toString(inputMessage.getBody(), "UTF-8"); Map mapJson = (Map) JSON.parseObject(string, Map.class); Map map = new HashMap(); Set entrySet = mapJson.entrySet(); for (Entry entry : entrySet) {String key = entry.getKey(); Object objValue = https://www.it610.com/article/entry.getValue(); if (objValue instanceof String) {String value = objValue.toString(); map.put(key, filterDangerString(value)); } else { // 针对结合的处理@SuppressWarnings("rawtypes")List parseArray = JSONArray.parseArray(objValue.toString(), HashMap.class); List listMap = new ArrayList(); for (Map innerMap : parseArray) {Map childrenMap = new HashMap(); Set elseEntrySet = innerMap.entrySet(); for (Entry en : elseEntrySet) {String innerKey = en.getKey(); Object innerObj = en.getValue(); if (innerObj instanceof String) {String value = https://www.it610.com/article/innerObj.toString(); childrenMap.put(innerKey, filterDangerString(value)); }}listMap.add(childrenMap); }map.put(key, listMap); }}this.headers = inputMessage.getHeaders(); this.body = IOUtils.toInputStream(JSON.toJSONString(map),"UTF-8"); } @Overridepublic InputStream getBody() throws IOException {return body; } @Overridepublic HttpHeaders getHeaders() {return headers; }}private String filterDangerString(String value) {if (value =https://www.it610.com/article/= null) {return null; }value = https://www.it610.com/article/value.replaceAll("\\|", ""); value = https://www.it610.com/article/value.replaceAll("&", ""); value = https://www.it610.com/article/value.replaceAll("; ", ""); value = https://www.it610.com/article/value.replaceAll("@", ""); value = https://www.it610.com/article/value.replaceAll("'", ""); value = https://www.it610.com/article/value.replaceAll("\\'", ""); value = https://www.it610.com/article/value.replaceAll("<", ""); value = https://www.it610.com/article/value.replaceAll("-", ""); value = https://www.it610.com/article/value.replaceAll(">", ""); value = https://www.it610.com/article/value.replaceAll("\\(", ""); value = https://www.it610.com/article/value.replaceAll("\\)", ""); value = https://www.it610.com/article/value.replaceAll("\\+", ""); value = https://www.it610.com/article/value.replaceAll("\r", ""); value = https://www.it610.com/article/value.replaceAll("\n", ""); value = https://www.it610.com/article/value.replaceAll("script", ""); value = https://www.it610.com/article/value.replaceAll("select", ""); value = https://www.it610.com/article/value.replaceAll("\"", ""); value = https://www.it610.com/article/value.replaceAll(">", ""); value = https://www.it610.com/article/value.replaceAll("<", ""); value = https://www.it610.com/article/value.replaceAll("=", ""); value = https://www.it610.com/article/value.replaceAll("/", ""); return value; }}

对于以上的配置Controller接收参数需要加@RequestBody。
测试
使用RequestBodyAdvice实现对Http请求非法字符过滤
文章图片

过滤后的数据
使用RequestBodyAdvice实现对Http请求非法字符过滤
文章图片

自定义RequestBodyAdvice过滤Json表情符号
/** * @Author: ZhiHao * @Date: 2021/6/4 19:03 * @Description: 过滤表情符号, POST-json请求 * @Versions 1.0 **/@ControllerAdvice@Slf4jpublic class FilterEmojiRequestBodyAdvice implements RequestBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) {Annotation[] annotations = methodParameter.getParameterAnnotations(); for (Annotation ann : annotations) {Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {return true; }}return false; }@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException {return inputMessage; }@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) {try {this.filterEmojiAfterBody(body); } catch (Exception e) {log.info("过滤表情异常:{}", e); }return body; }private void filterEmojiAfterBody(Object body) throws IllegalAccessException {if (null != body) {Field[] fields = ReflectUtil.getFields(body.getClass()); for (int i = 0; i < fields.length; i++) {Field field = fields[i]; if (field.isAnnotationPresent(Valid.class)) {field.setAccessible(true); this.filterEmojiAfterBody(field.get(body)); }if (field.isAnnotationPresent(FilterEmoji.class)) {field.setAccessible(true); Object value = https://www.it610.com/article/field.get(body); if (value instanceof String) {String str = filterEmoji(value.toString()); field.set(body, str); }}}}}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) {return body; }/*** 过滤emoji 或者 其他非文字类型的字符** @param source* @return*/public static String filterEmoji(String source) {if (StringUtils.isEmpty(source)) {return ""; }if (!containsEmoji(source)) {return source; //如果不包含,直接返回}StringBuilder buf = new StringBuilder(); int len = source.length(); for (int i = 0; i < len; i++) {char codePoint = source.charAt(i); if (isNotEmojiCharacter(codePoint)) {buf.append(codePoint); }}return buf.toString().trim(); }/*** 检测是否有emoji字符** @param source* @return 一旦含有就抛出*/public static boolean containsEmoji(String source) {if (StringUtils.isBlank(source)) {return false; }int len = source.length(); for (int i = 0; i < len; i++) {char codePoint = source.charAt(i); if (!isNotEmojiCharacter(codePoint)) {//判断到了这里表明,确认有表情字符return true; }}return false; }/*** 判断是否为非Emoji字符** @param codePoint 比较的单个字符* @return*/public static boolean isNotEmojiCharacter(char codePoint) {return (codePoint == 0x0) ||(codePoint == 0x9) ||(codePoint == 0xA) ||(codePoint == 0xD) ||((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)); }}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

    推荐阅读