使用RequestBodyAdvice实现对Http请求非法字符过滤
RequestBodyAdvice对Http请求非法字符过滤
利用RequestBodyAdvice对HTTP请求参数放入body中的参数进行非法字符过滤。
要求:spring 4.2+
额外的pom.xml
org.apache.commons commons-io1.3.2 com.alibaba fastjson1.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 extends HttpMessageConverter>> converterType) {return true; }@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class extends HttpMessageConverter>> converterType) {return body; } @Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class extends HttpMessageConverter>> 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 extends HttpMessageConverter>> 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(); SetentrySet = 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
对于以上的配置Controller接收参数需要加@RequestBody。
测试
文章图片
过滤后的数据
文章图片
自定义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 extends HttpMessageConverter>> 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 extends HttpMessageConverter>> converterType) throws IOException {return inputMessage; }@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> 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 extends HttpMessageConverter>> 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)); }}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
推荐阅读
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入