springboot清除字符串前后空格与防xss攻击
一、查看WebMvcAutoConfiguration.class中的方法源码
1
2
3
4
5
6
7
|
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
try {
//从容器中获取
return (ConfigurableWebBindingInitializer) this .beanFactory.getBean(ConfigurableWebBindingInitializer. class );
} catch (NoSuchBeanDefinitionException ex) {
return super .getConfigurableWebBindingInitializer();
}
|
可以发现ConfigurableWebBindingInitializer是从容器(beanFactory)中获取到的,所以我们可以配置一个
ConfigurableWebBindingInitializer来替换默认的,只需要在容器中添加一个我们自定义的转换器即可。
当我们创建了自己的ConfigurableWebBindingInitializer这个Bean,Spring boot就会自动使用它来配置Spring MVC实现参数的类型转换。
二、自定义属性编辑器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
/**
*
* @description 与spring mvc的@InitBinder结合 用于防止XSS攻击
*/
class StringEscapeEditor extends PropertyEditorSupport {
/** 转义HTML */
private boolean escapeHTML;
/** 转义javascript */
private boolean escapeJavaScript;
/** 是否将空字符串转换为null */
private final boolean emptyAsNull;
/** 是否去掉前后空格 */
private final boolean trimmed;
public StringEscapeEditor() {
this ( true , true , false , true );
}
public StringEscapeEditor( boolean escapeHTML, boolean escapeJavaScript) {
this ( true , true ,escapeHTML,escapeJavaScript);
}
public StringEscapeEditor( boolean emptyAsNull, boolean trimmed, boolean escapeHTML, boolean escapeJavaScript) {
super ();
this .emptyAsNull = emptyAsNull;
this .trimmed = trimmed;
this .escapeHTML = escapeHTML;
this .escapeJavaScript = escapeJavaScript;
}
@Override
public String getAsText() {
Object value = getValue();
if (Objects.nonNull(value))
{
return value.toString();
}
return value != null ? value.toString() : null ;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
String value = text;
if (value == null || emptyAsNull && text.isEmpty()) {
//do nothing
} else if (trimmed) {
//去字符传参数前后空格
value = value.trim();
}
if (escapeHTML) {
//HTML转义(防止XSS攻击)
//HtmlUtils.htmlEscape 默认的是ISO-8859-1编码格式,会将中文的某些符号进行转义。
//如果不想让中文符号进行转义请使用UTF-8的编码格式。例如:HtmlUtils.htmlEscape(text, "UTF-8")
value = HtmlUtils.htmlEscape(value, "UTF-8" );
}
if (escapeJavaScript) {
//javascript转义(防止XSS攻击)
value = JavaScriptUtils.javaScriptEscape(value);
}
setValue(value);
}
}
|
三、创建WebBindingInitializerConfiguration类
加上@Bean注解,交给spring容器管理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@Configuration
public class WebBindingInitializerConfiguration {
@Bean
public ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
FormattingConversionService conversionService = new DefaultFormattingConversionService();
//we can add our custom converters and formatters
//conversionService.addConverter(...);
//conversionService.addFormatter(...);
initializer.setConversionService(conversionService);
//we can set our custom validator
//initializer.setValidator(....);
//here we are setting a custom PropertyEditor
initializer.setPropertyEditorRegistrar(propertyEditorRegistry -> {
propertyEditorRegistry.registerCustomEditor(String. class ,
new StringEscapeEditor());
});
return initializer;
}
}
|
springboot去除参数中前后空格说明
一、 需求
使用SpringBoot使用过滤器去除@RequestBody参数两端的空格;一般我们去普通的请求我们都会对请求参数进行验证。
Java也提供了@notNull和@notBlank这种验证方式,但是对@RequestBody 这种只能验证是不是非空,对数据两端的空格未进行处理,同时大家也不想遍历一遍参数然后再处理再封装到对象中,正好项目中有这个需要,所以就参考别的做了Post请求中针对application/json格式的有@RequestBody注解的参数进行了去空格处理
二、 解决方法
2.1 新建一个过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Component
@WebFilter (urlPatterns = "/**" , filterName = "ParamsFilter" , dispatcherTypes = DispatcherType.REQUEST)
public class ParamsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ParameterRequestWrapper parmsRequest = new ParameterRequestWrapper((HttpServletRequest) request);
chain.doFilter(parmsRequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
|
2.2 实现ParameterRequestWrapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.alibaba.fastjson.JSON;
/**
* @author :
* @description
* @date : 2021/4/22
*/
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String , String[]> params = new HashMap<>();
public ParameterRequestWrapper(HttpServletRequest request) {
super (request);
Map<String, String[]> requestMap=request.getParameterMap();
this .params.putAll(requestMap);
this .modifyParameterValues();
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (! super .getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){
return super .getInputStream();
}
String json = IOUtils.toString( super .getInputStream(), "utf-8" );
if (StringUtils.isEmpty(json)) {
return super .getInputStream();
}
Map<String,Object> map= jsonStringToMap(json);
ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes( "utf-8" ));
return new MyServletInputStream(bis);
}
public void modifyParameterValues(){
Set<String> set = params.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()){
String key= it.next();
String[] values = params.get(key);
values[ 0 ] = values[ 0 ].trim();
params.put(key, values);
}
}
@Override
public String getParameter(String name) {
String[]values = params.get(name);
if (values == null || values.length == 0 ) {
return null ;
}
return values[ 0 ];
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
class MyServletInputStream extends ServletInputStream {
private ByteArrayInputStream bis;
public MyServletInputStream(ByteArrayInputStream bis){
this .bis=bis;
}
@Override
public boolean isFinished() {
return true ;
}
@Override
public boolean isReady() {
return true ;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read(){
return bis.read();
}
}
public static Map<String, Object> jsonStringToMap(String jsonString) {
Map<String, Object> map = new HashMap<>();
JSONObject jsonObject = JSONObject.parseObject(jsonString);
for (Object k : jsonObject.keySet()) {
Object o = jsonObject.get(k);
if (o instanceof JSONArray) {
List<Map<String, Object>> list = new ArrayList<>();
Iterator<Object> it = ((JSONArray) o).iterator();
while (it.hasNext()) {
Object obj = it.next();
list.add(jsonStringToMap(obj.toString()));
}
map.put(k.toString(), list);
} else if (o instanceof JSONObject) {
map.put(k.toString(), jsonStringToMap(o.toString()));
} else {
if (o instanceof String) {
map.put(k.toString(), o.toString().trim());
} else {
map.put(k.toString(), o);
}
}
}
return map;
}
}
|
三、 完美解决
参数前后空格完美去除!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://www.jianshu.com/p/2b8ac1adb7a1