- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我的要求是解密用我自己的算法加密的请求体。
我尝试扩展 HttpServletRequestWrapper
并将新请求传递给 doFilter
。但是 getInputStream
和 getReader
都没有被调用,因此无法将请求正文解密为纯文本。
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/
我正在尝试使用 java/jsp 中的过滤器过滤掉名为“reason”的查询参数。 基本上,过滤器的作用是确保用户输入查看页面的“原因”。如果他们没有,则需要将他们重定向到“输入原因”页面。一旦他们输
在我的项目中,我有一组 api 调用,它们应该通过某些常见的验证集进行过滤。在这种情况下,我必须在请求到达 REST Controller 之前拦截请求,读取请求正文,进行验证并在请求通过验证时将其传
我正在尝试为我的 JSON 网络服务创建一个验证系统。这个想法是让一个拦截器捕获每个 Json @RequestBody,通过 JacksonMapping 用它创建一个 JSON 对象。然后从中读取
我有一个过滤器可以验证/授权 REST 调用。此过滤器需要访问请求参数,因此我为此编写了自定义 HTTPServletRequestWrapper。 import java.util.Collecti
我写了一个名为 HTTPRequest 的 HttpServletRequestWrapper,它读取完整的 HTTP POST 主体以供进一步使用。这个基于 http://natch3z.blogs
我有一个标准的 Spring MVC Controller (服务于 REST 调用),如下所示: @Controller public class SpringRestController {
我正在使用从“EAR A”到“EAR B”的编码形式。 当我尝试处理请求时: accion = "/decimprenta"; pagina = "/procesardeclaraci
我用的是Tomcat7。我的项目结构是: as1.jsp as2.jsp web.xml 的内容是: filter1 /as1.jsp
我的要求是解密用我自己的算法加密的请求体。 我尝试扩展 HttpServletRequestWrapper 并将新请求传递给 doFilter。但是 getInputStream 和 getReade
我目前正在使用 Jersey 库在 Java 中开发 RESTful Web 服务。 出于安全原因,我们需要类似于 Amazon 的简单存储服务的自定义身份验证。但是,这需要我计算正文(如果有的话)的
我想在 Servlet 请求中添加自定义 header 。 首先,我构建了一个HttpServletRequestWrapper类 public class HeaderRequest_DEBUG e
我正在尝试调整 HttpServletRequestWrapper(参见 How to read InputStream multiple times),以便在过滤器中使用 HTTP Post 正文后
我正在编写一个 Tomcat 应用程序,并根据 Google 的 oauth2 服务进行身份验证。我原本打算编写一个简单的 Filter 来进行身份验证,但无法在 Filter 中设置用户主体。根据我
我有一个过滤器,它接受传入请求,然后用 HttpServletRequestWrapper 包装它,而 HttpServletRequestWrapper 又具有 setParameter() 方法。
使用 HttpServletRequestWrapper 包装 HttpServletRequest 的目的是什么?我们这样做有什么好处? 最佳答案 HttpServletRequest是 HTTP
我在 Eclipse IDE 中使用 JBoss4.2。当我运行 hellojsf程序使用JSP View 技术,运行良好。当我尝试使用相同组件的 Facelets 时,出现以下异常: 2012-06
我是一名优秀的程序员,十分优秀!