spring boot自定义类继承AbstractJackson2HttpMessageConverter不起作用解决方法【原创】

java技术文章

2019-08-05

19

0

 前言

      最近在开发一个项目过程中,需要进行对输入内容进行防XSS攻击过滤,因为我们使用的架构是前后端分离,所有的请求数据都是json格式,并且有几个功能是上传图片接口,使用网上流传的XssFilter又获取不到requestBody请求体的内容,用数据流方式来获取的话,又会导致上传图片失败。进过一番搜索和琢磨后,发现可以使用spring boot继承自AbstractJackson2HttpMessageConverter的转换器来实现,但是加上转换器之后发现请求数据的时候,并没有执行当前自定义类里面的转换方法,最终经过源码跟踪以后发现可以使用如下方法来实现。

原因

    搜索了网上的大部分资料,如果要自定义requestbody中的json数据,只需要继承自WebMvcConfigurationSupport类,然后在spring boot启动程序中注入当前bean就可以了(这里叫方式一),如果WebApplication没有启用@EnableWebMvc,这样也许是可以的(我也没试验过),但是如果是启用了@EnableWebMvc,这样的话,应用是不会执行我们自定义的自定义类的。

这里是spring boot源码:

WebMvcConfigurationSupport类中有这么一段代码:

/**
	 * Provides access to the shared {@link HttpMessageConverter HttpMessageConverters}
	 * used by the {@link RequestMappingHandlerAdapter} and the
	 * {@link ExceptionHandlerExceptionResolver}.
	 * <p>This method cannot be overridden; use {@link #configureMessageConverters} instead.
	 * Also see {@link #addDefaultHttpMessageConverters} for adding default message converters.
	 */
	protected final List<HttpMessageConverter<?>> getMessageConverters() {
		if (this.messageConverters == null) {
			this.messageConverters = new ArrayList<>();
			configureMessageConverters(this.messageConverters);
			if (this.messageConverters.isEmpty()) {
				addDefaultHttpMessageConverters(this.messageConverters);
			}
			extendMessageConverters(this.messageConverters);
		}
		return this.messageConverters;
	}

      其中的configureMessageConverters方法就是加载我们自定义类的方法,但是如果是启用@EnableWebMvc的话,这里的方法执行的不是WebMvcConfigurationSupport的实现类,而是spring mvc的DelegatingWebMvcConfiguration实现类,所以这里就会导致我们按方式一来注入的时候不执行自定义类。

所以我们这里需要实现的是DelegatingWebMvcConfiguration类的中的方法:

@Override
	protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		this.configurers.configureMessageConverters(converters);
	}

而上面这个方法是不允许继承的,所以我们这里需要从this.configurers这个参数变量来着手,我们再看下this.configurers这个变量:

private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

而这个类又是继承自WebMvcConfigurer:

class WebMvcConfigurerComposite implements WebMvcConfigurer

所以这里我们自己实现一个WebMvcConfigurer自定义类,并在类中的方法中加入我们自己的json转换实现类,就可以了:

解决方法

     一、 添加json转换自定义类:XSSRequestBodyConverter

package com.mco.plateform.interceptor;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.apache.commons.lang3.StringEscapeUtils;
import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mco.basic.util.StringUtils;
import com.mco.plateform.configure.XssRequestWrapper;

public class XSSRequestBodyConverter extends AbstractJackson2HttpMessageConverter  {
	
	private static Policy policy = null;
   
	public XSSRequestBodyConverter(ObjectMapper objectMapper) {
		super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
        String path = XssRequestWrapper.class.getClassLoader().getResource("antisamy-anythinggoes-1.4.4.xml").getFile();
		if (path.startsWith("file")) {
			path = path.substring(6);
		}
		try {
			policy = Policy.getInstance(path);
		} catch (PolicyException e) {
			e.printStackTrace();
		}
    }

	@Override
	public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
	        throws IOException, HttpMessageNotReadableException {
	    Object requestBody = super.read(type, contextClass, inputMessage);
	    String requestInStr = JSONObject.toJSONString(requestBody);
	    if(StringUtils.isNotEmpty(requestInStr)&&requestInStr.startsWith("[")) {
	    	return JSONArray.parseArray(xssClean(requestInStr),(Class<?>)((ParameterizedType)type).getActualTypeArguments()[0]);
	    }else {
	    	return JSONObject.parseObject(xssClean(requestInStr), requestBody.getClass());
	    }
	    
//		return super.read(type, contextClass, inputMessage);
	}

	@SuppressWarnings("deprecation")
	private String xssClean(String value) {
		AntiSamy antiSamy = new AntiSamy();
		try {
			final CleanResults cr = antiSamy.scan(value, policy);
			String str = StringEscapeUtils.unescapeHtml4(cr.getCleanHTML());
			str = str.replaceAll(antiSamy.scan("&nbsp;", policy).getCleanHTML(), "");
			str = str.replaceAll("\"\\\\\"", "\\\\\"");
			str = str.replaceAll("\\\\\"\"", "\\\\\"");
			return str;
		} catch (ScanException e) {
			e.printStackTrace();
		} catch (PolicyException e) {
			e.printStackTrace();
		}
		return value;
	}
}

二、添加继承WebMvcConfigurer的实现类XssWebMvcConfigurer

@Configuration
public class XssWebMvcConfigurer implements WebMvcConfigurer {
	
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		converters.add(new XSSRequestBodyConverter(new ObjectMapper()));
	}
}

 这样就可以执行我们自定义的json转化类了。

 欢迎访问:www.hongfu951.com博客,查看更多文章

发表评论

全部评论:0条

鸿福951

努力打造一个好用的webui

热评文章

推荐文章