I'm mapping my request's JSON POST data into an object using Spring's @RequestBody
annotation and MappingJacksonHttpMessageConverter
. However after that I'd like to read the data in String
form to do some additional authentication. But when the marshalling has happened, the InputStream
in HttpServletRequest
is empty. Once I remove the @RequestBody
parameter from the method the reading of POST data into a String
works as expected.
Do I have to compromise by giving up the @RequestBody
and doing the binding somehow manually or is there a more elegant solution?
So, basically you need to compute a hash of the request body. The elegant way to do it is to apply a decorator to the InputStream
.
For example, inside a handler method (in this case you can't use @RequestBody
and need to create HttpMessageConverter
manually):
@RequestMapping(...)
public void handle(HttpServletRequest request) throws IOException {
final HashingInputStreamDecorator d =
new HashingInputStreamDecorator(request.getInputStream(), secretKey);
HttpServletRequest wrapper = new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() throws IOException {
return d;
}
};
HttpMessageConverter conv = ...;
Foo requestBody = (Foo) conv.read(Foo.class, new ServletServerHttpRequest(wrapper));
String hash = d.getHash();
...
}
where hash is computed incrementally in overriden read
methods of HashingInputStreamDecorator
.
You can also use @RequestBody
if you create a Filter
to apply the decorator. In this case decorator can pass the computed hash to the handler method as a request attribute. However, you need to map this filter carefully to apply it only to the requests to specific handler method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With