In the Spring Security authorization process (voting class, etc.) I think there are cases where you have to refer to the Body of the Request. (For example, when updating the DB with POST or PUT, etc.
However, in the HttpServletRequest class Body is a stream and can only be read once.
So this time, I will introduce how to read Body multiple times.
① Hold the information read from Body (2) Replace the Body acquisition source with the information in (1)
Stream class Set as the return type when calling HttpServletRequest.getInputStream () Use byte array for initialization
BufferedServletInputStream.java
public class BufferedServletInputStream extends ServletInputStream {
private ByteArrayInputStream inputStream;
//Initialize with byte array
public BufferedServletInputStream(byte[] buffer) {
this.inputStream = new ByteArrayInputStream(buffer);
}
@Override
public int available() throws IOException {
return inputStream.available();
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return inputStream.read(b, off, len);
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
}
Wrapper class for HttpServletRequest
BufferedServletRequestWrapper.java
public class BufferedServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] buffer;
public BufferedServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
//Get Stream from Request Body
InputStream is = request.getInputStream();
//Convert Stream to byte array and keep it in instance variable
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buff[] = new byte[1024];
int read;
while ((read = is.read(buff)) > 0) {
baos.write(buff, 0, read);
}
this.buffer = baos.toByteArray();
}
//Replace the body acquisition source with this method
@Override
public ServletInputStream getInputStream() throws IOException {
//Initialize Stream class and return
return new BufferedServletInputStream(this.buffer);
}
}
Filter class Replace by request by OncePerRequestFilter
MultipleReadEnableFilter.java
@Component
public class MultipleReadEnableFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//Initialize the wrapper class from HttpServletRequest
HttpServletRequest wrappedRequest = new BufferedServletRequestWrapper((HttpServletRequest) request);
filterChain.doFilter(wrappedRequest, response);
}
}
Set the created Filter in the Spring Security setting class
//Wrap to read inputStream multiple times
http.addFilter(multipleReadEnableFilter);
Recommended Posts