如何在 HttpServletRequest 上重写 POST 请求正文 [英] How to rewrite POST request body on HttpServletRequest
问题描述
我正在开发一个过滤器,我必须在其中获取请求有效负载、解密它、检查它是否是有效的 JSON 以及它是否与链一起继续并转到我的服务.问题是,到目前为止,我还没有找到重写正文的方法.为什么我要重写它?由于服务需要一个 JSON 并且请求的正文中有一个加密文本,一旦我解密它,我希望正文是解密的 JSON.此外,一旦我从服务返回,我应该重写响应以加密 json.我已经阅读了很多论坛和问题,但无法找到可行的解决方案.
I'm working on a Filter in which I have to get the request payload, decrypt it, check if it's a valid JSON and if it is go on with the chain and go to my service. The thing is that, so far I haven't been able to find a way to rewrite the body. Why I want to rewrite it? As the service expects a JSON and the request has an encrypted text in the body, once I decrypt it I want the body to be the decrypted JSON. Also, once I return from the service, I should rewrite the response to have the json encrypted. I've read a lot of forums and questions but couldn't get to a working solution.
这是我的代码:
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
}
}
还有包装器,以防万一:
And also the wrapper, just in case:
AuthenticationRequestWrapper.java
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;
}
}
希望这里有人知道我怎样才能让它工作.
Hopefully somebody here knows how I can get to get this working.
提前谢谢各位.
推荐答案
虽然你问的问题在技术上可能是可行的,但对我来说这听起来不是正确的方法.
Whilst what you are asking is probably technically possible, it doesn't sound like the right approach to me.
您需要的是一个位于传入请求(端点)和您的服务之间的安全层.重写请求的正文是一件很奇怪的事情(这可能解释了您遇到问题的原因).您是否有理由希望在 Filter
中完成此操作?毕竟,filters
旨在过滤请求,而不是重写它们 ;)
What you need is a security layer that sits between the incoming request (endpoint) and your service. Re-writing the body of the request is a strange thing to be doing (which probably explains why you're having issues). Is there a reason you want this to be done in a Filter
? After all, filters
are designed to filter requests, not rewrite them ;)
更合乎逻辑/透明的解决方案是让您的端点接受所有传入请求,在将请求传递到您的服务层之前对其进行解密和验证.像这样:
A more logical/transparent solution would be to have your endpoint accept all incoming requests, decrypt and validate them before passing the request onto your service tier. Something like this:
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...
}
}
这篇关于如何在 HttpServletRequest 上重写 POST 请求正文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!