使用RequestBodyAdvice實現(xiàn)對Http請求非法字符過濾
更新時間:2021年06月29日 10:29:59 作者:盲目的拾荒者
這篇文章主要介紹了使用RequestBodyAdvice實現(xiàn)對Http請求非法字符過濾的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
RequestBodyAdvice對Http請求非法字符過濾
利用RequestBodyAdvice對HTTP請求參數(shù)放入body中的參數(shù)進(jìn)行非法字符過濾。
要求:spring 4.2+
額外的pom.xml
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency>
代碼
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:解釋 * 允許在將請求的主體讀取和轉(zhuǎn)換成一個對象之前對請求進(jìn)行自定義, * 并允許在將其傳遞到控制器方法作為一個@RequestBody或HttpEntity方法參數(shù)之前處理結(jié)果對象。 * * @author niugang * */ @ControllerAdvice(basePackages = "com.niugang") public class MyRequestBodyAdvice implements RequestBodyAdvice { private final static Logger logger = LoggerFactory.getLogger(MyRequestBodyAdvice.class); @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { return true; } @Override public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { return body; } @Override public 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; } } @Override public 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<String, Object> mapJson = (Map<String, Object>) JSON.parseObject(string, Map.class); Map<String, Object> map = new HashMap<String, Object>(); Set<Entry<String, Object>> entrySet = mapJson.entrySet(); for (Entry<String, Object> entry : entrySet) { String key = entry.getKey(); Object objValue = entry.getValue(); if (objValue instanceof String) { String value = objValue.toString(); map.put(key, filterDangerString(value)); } else { // 針對結(jié)合的處理 @SuppressWarnings("rawtypes") List<HashMap> parseArray = JSONArray.parseArray(objValue.toString(), HashMap.class); List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>(); for (Map<String, Object> innerMap : parseArray) { Map<String, Object> childrenMap = new HashMap<String, Object>(); Set<Entry<String, Object>> elseEntrySet = innerMap.entrySet(); for (Entry<String, Object> en : elseEntrySet) { String innerKey = en.getKey(); Object innerObj = en.getValue(); if (innerObj instanceof String) { String value = 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"); } @Override public InputStream getBody() throws IOException { return body; } @Override public HttpHeaders getHeaders() { return headers; } } private String filterDangerString(String value) { if (value == null) { return null; } value = value.replaceAll("\\|", ""); value = value.replaceAll("&", ""); value = value.replaceAll(";", ""); value = value.replaceAll("@", ""); value = value.replaceAll("'", ""); value = value.replaceAll("\\'", ""); value = value.replaceAll("<", ""); value = value.replaceAll("-", ""); value = value.replaceAll(">", ""); value = value.replaceAll("\\(", ""); value = value.replaceAll("\\)", ""); value = value.replaceAll("\\+", ""); value = value.replaceAll("\r", ""); value = value.replaceAll("\n", ""); value = value.replaceAll("script", ""); value = value.replaceAll("select", ""); value = value.replaceAll("\"", ""); value = value.replaceAll(">", ""); value = value.replaceAll("<", ""); value = value.replaceAll("=", ""); value = value.replaceAll("/", ""); return value; } }
對于以上的配置Controller接收參數(shù)需要加@RequestBody。
測試
過濾后的數(shù)據(jù)
自定義RequestBodyAdvice過濾Json表情符號
/** * @Author: ZhiHao * @Date: 2021/6/4 19:03 * @Description: 過濾表情符號, POST-json請求 * @Versions 1.0 **/ @ControllerAdvice @Slf4j public class FilterEmojiRequestBodyAdvice implements RequestBodyAdvice { @Override public 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; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException { return inputMessage; } @Override public 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 = field.get(body); if (value instanceof String) { String str = filterEmoji(value.toString()); field.set(body, str); } } } } } @Override public 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)) { //判斷到了這里表明,確認(rèn)有表情字符 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)); } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java Spring數(shù)據(jù)單元配置過程解析
這篇文章主要介紹了Java Spring數(shù)據(jù)單元配置過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-12-12SpringSecurity?用戶帳號已被鎖定的問題及解決方法
這篇文章主要介紹了SpringSecurity?用戶帳號已被鎖定,本文給大家分享問題原因及解決方式,需要的朋友可以參考下2023-12-12java調(diào)用百度定位api服務(wù)獲取地理位置示例
java調(diào)用百度定位api服務(wù)獲取地理位置示例,大家參考使用吧2013-12-12Spring Boot 會員管理系統(tǒng)之處理文件上傳功能
Spring Boot會員管理系統(tǒng)的中,需要涉及到Spring框架,SpringMVC框架,Hibernate框架,thymeleaf模板引擎。這篇文章主要介紹了Spring Boot會員管理系統(tǒng)之處理文件上傳功能,需要的朋友可以參考下2018-03-03面試題:java中為什么foreach中不允許對元素進(jìn)行add和remove
讀者遇到了一個比較經(jīng)典的面試題,也就是標(biāo)題上說的,為什么 foreach 中不允許對元素進(jìn)行 add 和 remove,本文就詳細(xì)的介紹一下,感興趣的可以了解一下2021-10-10