背景
基于SpringBoot项目,需要通过拦截器、过滤器对token,url(包括参数),进行过滤,进行权限或重复提交的过滤,配置后,被过滤的请求的URL出现“JSON parse error: Invalid UTF-8 start byte 0xb7 异常”(本地idea无异常,jar包运行出现)
原理
对于json格式请求参数,使用到request包装类RequestWrapper继承HttpServletRequestWrapper,因为inputStrream流只能读取一次,在拦截器中获取到值进行验证后,在controller中就获取不到值了,所以使用RequestWrapper将数据保存。但是windows环境下cmd运行jar包默认使用GBK编码格式,而在运行程序时RequestWrapper读取流的时候默认使用的是运行环境的编码格式也就是GBK,而我们一般使用的utf-8格式,所以会出现JSON parse error: Invalid UTF-8 start byte 0xb7 异常或者中文参数乱码
package com.neusoft.common.xss;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* @description: 自定义request wrapper用于对请求体中的报文进行处理
*/
public class RepeatHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public RepeatHttpServletRequestWrapper(HttpServletRequest request) throws IOException
{
super(request);
BufferedReader reader = request.getReader();
try (StringWriter writer = new StringWriter()) {
int read;
char[] buf = new char[1024 * 8];
while ((read = reader.read(buf)) != -1) {
writer.write(buf, 0, read);
}
// 需要以utf-8格式读取request中的数据,否则会乱码
this.body = writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8);
}
}
@Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
return new ServletInputStream()
{
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
public int read() throws IOException
{
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
解决方式
解决方式一:
全局搜索源码:
getBytes(Charset.defaultCharset())
替换为
getBytes(StandardCharsets.UTF_8)解决方式二:
启动方式:Java -Dfile.encoding=UTF-8 -jar xxxx.jar