ims内容的json内容格式过滤

This commit is contained in:
黎润豪 2026-03-25 16:23:33 +08:00
parent 1efa2feee9
commit a258db21a4
3 changed files with 124 additions and 4 deletions

View File

@ -36,4 +36,17 @@ public class FilterConfig {
registrationBean.setOrder(-100);
return registrationBean;
}
/**
* IMS请求编码预处理过滤器
*/
@Bean
public FilterRegistrationBean<ImsRequestFilter> imsRequestFilter() {
FilterRegistrationBean<ImsRequestFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new ImsRequestFilter());
registrationBean.addUrlPatterns("/ims/*");
registrationBean.setName("imsRequestFilter");
registrationBean.setOrder(-101);
return registrationBean;
}
}

View File

@ -0,0 +1,111 @@
package com.chinaweal.aiccs.config;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;
@Slf4j
public class ImsRequestFilter implements Filter {
// 匹配不可见字符控制字符0-31和127以及零宽字符
private static final Pattern INVISIBLE_CHAR_PATTERN = Pattern.compile(
"[\\x00-\\x1f\\x7f\\u200b-\\u200f\\u2028\\u2029\\ufeff]"
);
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// 只处理 JSON 请求
String contentType = request.getContentType();
if (contentType != null && contentType.contains("application/json")) {
CachedBodyHttpServletRequest cachedRequest =
new CachedBodyHttpServletRequest(request);
String body = cachedRequest.getBody();
// 移除不可见字符
String cleanedBody = INVISIBLE_CHAR_PATTERN.matcher(body).replaceAll("");
if (!cleanedBody.equals(body)) {
log.warn("ImsRequestFilter removed invisible characters from request body");
}
cachedRequest.updateBody(cleanedBody);
chain.doFilter(cachedRequest, resp);
} else {
chain.doFilter(req, resp);
}
}
private static class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
private byte[] cachedBody;
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
this.cachedBody = baos.toByteArray();
}
public String getBody() {
return new String(cachedBody, StandardCharsets.UTF_8);
}
public void updateBody(String body) {
this.cachedBody = body.getBytes(StandardCharsets.UTF_8);
}
@Override
public ServletInputStream getInputStream() {
return new CachedBodyServletInputStream(cachedBody);
}
@Override
public BufferedReader getReader() {
return new BufferedReader(
new InputStreamReader(getInputStream(), StandardCharsets.UTF_8)
);
}
}
private static class CachedBodyServletInputStream extends ServletInputStream {
private final ByteArrayInputStream delegate;
public CachedBodyServletInputStream(byte[] body) {
this.delegate = new ByteArrayInputStream(body);
}
@Override
public boolean isFinished() {
return delegate.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener listener) {
// non-blocking read not supported for cached body
}
@Override
public int read() {
return delegate.read();
}
}
}

View File

@ -79,10 +79,6 @@ spring:
multipart:
max-file-size: 100MB
max-request-size: 100MB
jackson:
parser:
# 允许解析未转义的控制字符(解决你那个中文括号/隐形字符报错)
allow-unquoted-control-chars: true
restLog:
ignoreServletPath: /druid,/swagger-resources,/v2/api-docs,/webjars,/user/checkSSOLogin