gpt4 book ai didi

java - HttpServletRequestWrapper 在 Spring 4 下不工作

转载 作者:太空宇宙 更新时间:2023-11-04 13:07:36 25 4
gpt4 key购买 nike

我的要求是解密用我自己的算法加密的请求体。

我尝试扩展 HttpServletRequestWrapper 并将新请求传递给 doFilter。但是 getInputStreamgetReader 都没有被调用,因此无法将请求正文解密为纯文本。

EncryptFilter 的顺序首先在 web.xml 中设置。

我使用的 URL 是 POST/user/add

这是我的代码

HttpServletRequestWrapper 的子类:

class ResettableStreamHttpServletRequest extends
HttpServletRequestWrapper {

private byte[] rawData;
private HttpServletRequest request;
private ResettableServletInputStream servletStream;

public ResettableStreamHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
this.servletStream = new ResettableServletInputStream();
}


public void resetInputStream(byte[] data) {
servletStream.stream = new ByteArrayInputStream(data);
}

@Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}

@Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return new BufferedReader(new InputStreamReader(servletStream));
}


private class ResettableServletInputStream extends ServletInputStream {

private InputStream stream;

@Override
public int read() throws IOException {
return stream.read();
}
}
}

doFilter相关代码:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest newRequest = new ResettableStreamHttpServletRequest((HttpServletRequest) request);
ServletResponse newResponse = new EncryptedResponseWrapper((HttpServletResponse) response);

String body = IOUtils.toString(newRequest.getInputStream());
String plainText = crypt.decrypt(body);
LOGGER.debug(plainText);
((ResettableStreamHttpServletRequest) newRequest).resetInputStream(plainText.getBytes("UTF-8"));

chain.doFilter(newRequest, newResponse);

if (((EncryptedResponseWrapper) newResponse).getStatus() != HttpStatus.OK.value()) {
response.getWriter().write(newResponse.toString());
return;
}

String text = newResponse.toString();
if (text != null) {
String respPlainText = newResponse.toString();
LOGGER.debug(respPlainText);
String encrypted = crypt.encrypt(respPlainText);
response.getWriter().write(encrypted);
}
}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<absolute-ordering>
<name>EncryptFilter</name>
<name>encodingFilter</name>
</absolute-ordering>

<filter>
<filter-name>EncryptFilter</filter-name>
<filter-class>com.yuexunit.micro.filter.EncryptFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncryptFilter</filter-name>
<url-pattern>/user/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

最佳答案

我使用这种方法转储请求来解决错误,但是由于当您使用 getReader() 将请求保存为字节数组时,您正在使用默认的机器编码,因此您不遵守请求的字符集,因此我遇到了错误。

在我的例子中,客户端执行了一个 POST,其有效负载使用 UTF-8 进行编码,但我的后端恰好位于 Windows 计算机上,其编码是 CP-1252。您的过滤器有效地接受 UTF-8 请求,将其转换为 CP-1252,并且所有后续过滤器都会看到这一点。就我而言,我有一个 REST Controller 期望接收该字符串 (JSON),因此我收到了“400 Bad Request”错误。

固定的解决方案围绕这些行(还没有尝试过!):

class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper {
private byte[] rawData;
private HttpServletRequest request;
private ResettableServletInputStream servletStream;

ResettableStreamHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
this.servletStream = new ResettableServletInputStream();
}

void resetInputStream() {
servletStream.stream = new ByteArrayInputStream(rawData);
}

@Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getInputStream());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}

@Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getInputStream());
servletStream.stream = new ByteArrayInputStream(rawData);
}
String encoding = getCharacterEncoding();
if (encoding != null) {
return new BufferedReader(new InputStreamReader(servletStream, encoding));
} else {
return new BufferedReader(new InputStreamReader(servletStream));
}
}

private class ResettableServletInputStream extends ServletInputStream {
private InputStream stream;

@Override
public int read() throws IOException {
return stream.read();
}
}
}

关于java - HttpServletRequestWrapper 在 Spring 4 下不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34280529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com