赞
踩
spring处理json是通过MappingJackson2HttpMessageConverter实现的。
而MappingJackson2HttpMessageConverter中的read()和writeInternal()分别对应json的请求和响应。
也就是说我们的过滤工作就这两个方法中展开。
writeInternal首先创建一个类并继承MappingJackson2HttpMessageConverter,我创建的是XSSMappingJackson2HttpMessageConverter
在spring-mvc.xml中找到
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
//中间省略
</bean>
将MappingJackson2HttpMessageConverter替换成XSSMappingJackson2HttpMessageConverter
打开XSSMappingJackson2HttpMessageConverter,重写read()
@Override public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { JavaType javaType = getJavaType(type, contextClass); Object obj = readJavaType(javaType, inputMessage); String json = super.getObjectMapper().writeValueAsString(obj); json = cleanXSS(json.toString()); Object obj1 = super.getObjectMapper().readValue(json, javaType); return obj1; } // 这个就是父类的readJavaType方法,由于父类该方法是private的,所以我们copy一个用 private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) { try { return super.getObjectMapper().readValue(inputMessage.getBody(), javaType); } catch (IOException ex) { throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex); } } private String cleanXSS(String value) { return Jsoup.clean(value.toString(), Whitelist.relaxed()); }
以上RequestBody的XSS过滤就完成,接下来是ResponseBody的过滤
// 重写writeInternal方法,在返回内容前首先进行加密
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
// 使用Jackson的ObjectMapper将Java对象转换成Json String
String json = super.getObjectMapper().writeValueAsString(object);
String result = cleanXSS(json.toString());
// 输出
outputMessage.getBody().write(result.getBytes());
}
完整代码
package com.meadin.funding.filter; import java.io.IOException; import java.lang.reflect.Type; import org.jsoup.Jsoup; import org.jsoup.safety.Whitelist; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; public class XSSMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { @Override public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { JavaType javaType = getJavaType(type, contextClass); Object obj = readJavaType(javaType, inputMessage); String json = super.getObjectMapper().writeValueAsString(obj); String result = cleanXSS(json.toString()); Object resultObj = super.getObjectMapper().readValue(result, javaType); return resultObj; } // 这个就是父类的readJavaType方法,由于父类该方法是private的,所以我们copy一个用 private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) { try { return super.getObjectMapper().readValue(inputMessage.getBody(), javaType); } catch (IOException ex) { throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex); } } // 重写writeInternal方法,在返回内容前首先进行加密 @Override protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { // 使用Jackson的ObjectMapper将Java对象转换成Json String String json = super.getObjectMapper().writeValueAsString(object); String result = cleanXSS(json.toString()); // 输出 outputMessage.getBody().write(result.getBytes()); } private String cleanXSS(String value) { return Jsoup.clean(value.toString(), Whitelist.relaxed()); } } <!--避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="mappingJacksonHttpMessageConverter" class="com.meadin.funding.filter.XSSMappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <!-- 要返回json格式正常必须设置为application/json;charset=UTF-8 --> <value>application/json;charset=UTF-8</value> </list> </property> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"> <!-- 属性值为null时隐藏 --> <property name="serializationInclusion"> <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value> </property> <!-- 处理responseBody 里面日期类型 --> <property name="dateFormat"> <bean class="java.text.SimpleDateFormat"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" /> </bean> </property> </bean> </property> </bean> <!-- 配合在实体类中的注解,将string类型自动转换成date类型存储 --> <mvc:annotation-driven> <mvc:message-converters> <ref bean="mappingJacksonHttpMessageConverter" /> </mvc:message-converters> </mvc:annotation-driven>
有关资料:
http://www.scienjus.com/custom-http-message-converter/
http://www.scienjus.com/spring-mvc-use-skill/#disqus_thread
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。