i am trying encrypt response data before it written into the HttpServletResponse, so i have implemented custom response wrapper and output streram and a filter classes,
Problem is i need to encrypt whole response data once, but there is no write(String content)
method, but there are three methods available inside ServletOutputStream class which are write(int b)
, write(byte[] b)
and write(byte[] b, int off, int len)
when i run the application only one method is called write(int b)
.
So is there any workaround to get whole response data as string, where i can call encrypt(responseData) ?
my classes looks like:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
BufferedRequestWrapper bufferedReqest = new BufferedRequestWrapper(httpServletRequest);
BufferedServletResponseWrapper bufferedResponse = new BufferedServletResponseWrapper(httpServletResponse);
// pass the wrappers on to the next entry
chain.doFilter(bufferedReqest, bufferedResponse);
}
and
public class BufferedServletResponseWrapper extends HttpServletResponseWrapper {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private ServletOutputStream outputStream;
private PrintWriter writer;
private MyServletOutputStream copier;
public BufferedServletResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
LOG.info("getOutputStream");
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
copier = new MyServletOutputStream(outputStream);
}
return copier;
}
@Override
public PrintWriter getWriter() throws IOException {
LOG.info("getWriter");
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
copier = new MyServletOutputStream(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
copier.flush();
}
}
public byte[] getCopy() {
if (copier != null) {
return copier.getCopy();
} else {
return new byte[0];
}
}
}
and my custom output stream class looks like:
public class MyServletOutputStream extends ServletOutputStream{
private final Logger LOG = LoggerFactory.getLogger(getClass());
private OutputStream outputStream;
private ByteArrayOutputStream copy;
public MyServletOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
this.copy = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
LOG.info("write int");
outputStream.write(b);
copy.write(b);
}
@Override
public void write(byte[] b) throws IOException {
LOG.info("write byte[]");
outputStream.write(b);
copy.write(b);
}
public byte[] getCopy() {
return copy.toByteArray();
}
}
String str= new String( bufferedResponse .getCopy());
This will give you the string of the data in outputStream. I can see in your code you are writing bytes to out as well as copier. This copier can also be modified later.
String encStr=Encrypt(str); // your encryption logic.
ServletOutputStream out= response.getOutputStream();
out.write(encStr.getByte()); //adding your encrypted data to response
out.flush();
out.close();
I have solved the problem by this way:
here is how response wrapper looks like:
public class BufferedServletResponseWrapper extends HttpServletResponseWrapper {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
private PrintWriter writer = new PrintWriter(outputStream);
public BufferedServletResponseWrapper(HttpServletResponse response)
throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
LOG.info("getOutputStream");
return new ServletOutputStream() {
@Override
public void write(int b) throws IOException {
LOG.info("write int");
outputStream.write(b);
}
@Override
public void write(byte[] b) throws IOException {
LOG.info("write byte[]");
outputStream.write(b);
}
};
}
@Override
public PrintWriter getWriter() throws IOException {
LOG.info("getWriter");
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
outputStream.flush();
}
}
public String getResponseData() {
return outputStream.toString();
}
}
and doFilter() looks like:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
BufferedServletResponseWrapper bufferedResponse = new BufferedServletResponseWrapper(
httpServletResponse);
// pass the wrappers on to the next entry
chain.doFilter(httpServletRequest, bufferedResponse);
String responseData = bufferedResponse.getResponseData();
String encryptedResponseData = encrypt(responseData);
OutputStream outputStream = httpServletResponse.getOutputStream();
outputStream.write(encryptedResponseData.getBytes());
outputStream.flush();
outputStream.close();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.