Java 如何在HttpServletRequest上重写POST请求正文

Java 如何在HttpServletRequest上重写POST请求正文,java,servlets,post,encryption,Java,Servlets,Post,Encryption,我正在开发一个过滤器,在这个过滤器中,我必须获取请求负载,解密它,检查它是否是有效的JSON,以及它是否与链一起运行并转到我的服务。问题是,到目前为止,我还没有找到一种重写身体的方法。我为什么要重写它?由于服务需要一个JSON,请求的正文中有一个加密的文本,所以一旦我解密了它,我希望正文就是解密后的JSON。此外,一旦我从服务返回,我应该重写响应以对json进行加密。我读过很多论坛和问题,但都找不到有效的解决方案 这是我的密码: RequestLoginFilter.java @WebF

我正在开发一个过滤器,在这个过滤器中,我必须获取请求负载,解密它,检查它是否是有效的JSON,以及它是否与链一起运行并转到我的服务。问题是,到目前为止,我还没有找到一种重写身体的方法。我为什么要重写它?由于服务需要一个JSON,请求的正文中有一个加密的文本,所以一旦我解密了它,我希望正文就是解密后的JSON。此外,一旦我从服务返回,我应该重写响应以对json进行加密。我读过很多论坛和问题,但都找不到有效的解决方案

这是我的密码:

RequestLoginFilter.java

    @WebFilter("/RequestLoginFilter")
public class RequestLoginFilter implements Filter{

    protected final static Log logger = LogFactory.getLog(RequestLoginFilter.class);

    private ServletContext context;

    private CryptoUtil crypto;

    public void init(FilterConfig fConfig) throws ServletException {
        this.context = fConfig.getServletContext();
        this.context.log("RequestLoggingFilter initialized");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//       use wrapper to read multiple times the content
        AuthenticationRequestWrapper req = new AuthenticationRequestWrapper((HttpServletRequest) request);
        HttpServletResponse resp = (HttpServletResponse) response;

        String payload = req.getPayload();
        try {
            String decryptedPayload = crypto.decrypt(payload);
            JSONUtils.convertJSONStringToObject(decryptedPayload, LoginTokenTO.class);
        } catch (GeneralSecurityException e) {
            logger.error("Error when trying to decrypt payload '"+payload+"'");
            throw new ServletException("Error when trying to decrypt payload '"+payload+"'", e);
        }
        chain.doFilter(req, resp);
        System.out.println("a ver");
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}
public class AuthenticationRequestWrapper extends HttpServletRequestWrapper {

    protected final static Log logger = LogFactory.getLog(AuthenticationRequestWrapper.class);

    private final String payload;

    public AuthenticationRequestWrapper (HttpServletRequest request) throws AuthenticationException {
        super(request);

        // read the original payload into the payload variable
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            // read the payload into the StringBuilder
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                // make an empty string since there is no payload
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            logger.error("Error reading the request payload", ex);
            throw new AuthenticationException("Error reading the request payload", ex);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException iox) {
                    // ignore
                }
            }
        }
        payload = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream () throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(payload.getBytes());
        ServletInputStream inputStream = new ServletInputStream() {
            public int read () 
                throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return inputStream;
    }

    public String getPayload() {
        return payload;
    }
}
还有包装,以防万一:

AuthenticationRequestWrapper.java

    @WebFilter("/RequestLoginFilter")
public class RequestLoginFilter implements Filter{

    protected final static Log logger = LogFactory.getLog(RequestLoginFilter.class);

    private ServletContext context;

    private CryptoUtil crypto;

    public void init(FilterConfig fConfig) throws ServletException {
        this.context = fConfig.getServletContext();
        this.context.log("RequestLoggingFilter initialized");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//       use wrapper to read multiple times the content
        AuthenticationRequestWrapper req = new AuthenticationRequestWrapper((HttpServletRequest) request);
        HttpServletResponse resp = (HttpServletResponse) response;

        String payload = req.getPayload();
        try {
            String decryptedPayload = crypto.decrypt(payload);
            JSONUtils.convertJSONStringToObject(decryptedPayload, LoginTokenTO.class);
        } catch (GeneralSecurityException e) {
            logger.error("Error when trying to decrypt payload '"+payload+"'");
            throw new ServletException("Error when trying to decrypt payload '"+payload+"'", e);
        }
        chain.doFilter(req, resp);
        System.out.println("a ver");
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}
public class AuthenticationRequestWrapper extends HttpServletRequestWrapper {

    protected final static Log logger = LogFactory.getLog(AuthenticationRequestWrapper.class);

    private final String payload;

    public AuthenticationRequestWrapper (HttpServletRequest request) throws AuthenticationException {
        super(request);

        // read the original payload into the payload variable
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            // read the payload into the StringBuilder
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                // make an empty string since there is no payload
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            logger.error("Error reading the request payload", ex);
            throw new AuthenticationException("Error reading the request payload", ex);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException iox) {
                    // ignore
                }
            }
        }
        payload = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream () throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(payload.getBytes());
        ServletInputStream inputStream = new ServletInputStream() {
            public int read () 
                throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return inputStream;
    }

    public String getPayload() {
        return payload;
    }
}
希望这里有人知道我怎样才能让它工作


提前感谢各位。

虽然你们所问的在技术上可能是可行的,但对我来说,这似乎不是正确的方法

您需要的是位于传入请求(端点)和服务之间的安全层。重新编写请求的主体是一件奇怪的事情(这可能解释了您遇到问题的原因)。您希望在
过滤器中执行此操作是否有原因?毕竟,
过滤器设计用于过滤请求,而不是重写请求;)

一个更合理/透明的解决方案是让您的端点接受所有传入的请求,在将请求传递到您的服务层之前对它们进行解密和验证。大概是这样的:

public void handleRequest(Request request) {
    try {
        IncomingRequest x = securityManager.decrypt(request);
        Response r = myService.handleRequest(x);
        handleResponse(securityManager.encrypt(r));
    }catch(InvlidateMessage x) {
        handleInvalidMessage...
    }catch(BusinessException x) {
        handleBusinessException...
    }
}