如何实现 multipart/form-data 内容类型的过滤器,我为 application/json 做了它,它工作正常,但在为 multipart/form-data 类型的请求实现它时遇到了困难,下面是 application/json 的代码。我是否必须为它编写一个不同的过滤器,或者我可以在同一个过滤器中管理它,如果有人告诉我如何以正确的方式做到这一点,我将不胜感激。
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
@Component
public class XSSFilter implements Filter {
@Override
public void doFilter(
ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
filterChain.doFilter(
new XSSRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}
}
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
public class XSSRequestWrapper extends HttpServletRequestWrapper {
private final String requestJsonString;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
public XSSRequestWrapper(HttpServletRequest httpServletRequest) {
super(httpServletRequest);
try {
StringBuilder stringBuilder = new StringBuilder();
bufferedReader = httpServletRequest.getReader();
char[] charBuffer = new char[128];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) != -1) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
requestJsonString = stringBuilder.toString();
JsonNode jsonNode = new ObjectMapper().readTree(requestJsonString);
processJsonNode(jsonNode);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Override
public ServletInputStream getInputStream() {
return new ServletInputStreamWrapper(requestJsonString.getBytes());
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
private void processJsonNode(JsonNode jsonNode) {
if (jsonNode.isObject()) {
jsonNode.fields().forEachRemaining(entry -> processJsonNode(entry.getValue()));
} else if (jsonNode.isArray()) {
jsonNode.elements().forEachRemaining(this::processJsonNode);
} else {
sanitize("key", jsonNode.asText());
}
}
@Override
public Enumeration<String> getHeaderNames() {
Enumeration<String> headerNames = super.getHeaderNames();
Collections.list(headerNames)
.forEach(headerName -> sanitize(headerName, getHeader(headerName)));
return headerNames;
}
@Override
public String[] getParameterValues(String parameter) {
String[] parameterValues = super.getParameterValues(parameter);
Arrays.stream(parameterValues).forEach(value -> sanitize(parameter, value));
return parameterValues;
}
public void sanitize(String key, String value) {
Safelist safelist = Safelist.none();
Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
if (!value.equalsIgnoreCase(Jsoup.clean(value, "", safelist, outputSettings))) {
throw new SecurityException(
"XSS attack error, by the key '" + key + "' and the value is '" + value + "'");
}
}
}
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.IOException;
public class ServletInputStreamWrapper extends ServletInputStream {
private final byte[] data;
private int idx = 0;
public ServletInputStreamWrapper(byte[] data) {
this.data = data;
}
@Override
public int read() throws IOException {
if (idx >= data.length) {
return -1;
}
return data[idx++];
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {}
}
您可以从 HttpServletRequest 检查内容类型标头值,并分别应用 multipart/form-data 和 application/json 的逻辑。
if (MULTIPART_FORM_DATA_VALUE.equals(httpServletRequest.getContentType())) {
} else if (APPLICATION_JSON_VALUE.equals(httpServletRequest.getContentType())) {
}