오늘이군
@RequestBody Json 출력필터 적용 - xss 본문
반응형
이전 글에서 Request 를 Wrapping 하여 악의적인 공격 구문을 필터링하여 입력하기도 하고
Mapper가 JSON 문자열을 생성할 때 char 를 변환하여 출력하기도 하였습니다.
막상 배포를 해보니 char 를 변환하여 출력하는 것에는 일정한 규칙(예외) 를 적용 하지 못하여
Request 를 Wrapping 한 것 처럼 Response 를 Wrapping 할 수 있지 않을까 하여 찾아본 내용을 공유 합니다.
stackoverflow 에서 가져 왔고요 아래 filter 를 web.xml, WebConfig, WebMvcConfig 같은 곳에 적용해주시면 됩니다.
import com.navercorp.lucy.security.xss.servletfilter.XssEscapeFilter;
import org.springframework.http.MediaType;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;
public class CustomJsonFilter implements Filter {
private XssEscapeFilter xssEscapeFilter = XssEscapeFilter.getInstance();
private FilterConfig filterConfig = null;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
CharResponseWrapper wrappedResponse = new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrappedResponse);
byte[] bytes = wrappedResponse.getByteArray();
if (wrappedResponse.isJsonResponse()) {
String out = filterString(new String(bytes));
response.getOutputStream().write(out.getBytes());
} else {
response.getOutputStream().write(bytes);
}
}
private String filterString(String inputString) {
return xssEscapeFilter.doFilter(null, null, inputString);
}
private static class ByteArrayServletStream extends ServletOutputStream {
ByteArrayOutputStream baos;
ByteArrayServletStream(ByteArrayOutputStream baos) {
this.baos = baos;
}
public void write(int param) {
baos.write(param);
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener listener) {}
}
private static class ByteArrayPrintWriter {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PrintWriter pw = new PrintWriter(baos);
private ServletOutputStream sos = new ByteArrayServletStream(baos);
public PrintWriter getWriter() {
return pw;
}
public ServletOutputStream getStream() {
return sos;
}
byte[] toByteArray() {
return baos.toByteArray();
}
}
private static class CharResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayPrintWriter output;
private boolean usingWriter;
public CharResponseWrapper(HttpServletResponse response) {
super(response);
usingWriter = false;
output = new ByteArrayPrintWriter();
}
public byte[] getByteArray() {
return output.toByteArray();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (usingWriter) {
super.getOutputStream();
}
usingWriter = true;
return output.getStream();
}
@Override
public PrintWriter getWriter() throws IOException {
if (usingWriter) {
super.getWriter();
}
usingWriter = true;
return output.getWriter();
}
public String toString() {
return output.toString();
}
public boolean isJsonResponse() {
return Objects.nonNull(super.getResponse().getContentType())
&& super.getResponse().getContentType().contains(MediaType.APPLICATION_JSON_VALUE);
}
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void destroy() {
filterConfig = null;
}
}
반응형
'삶.. > 프로그래밍' 카테고리의 다른 글
로그수집서버 아키텍처 알아보기 (0) | 2020.05.22 |
---|---|
Redis 살펴보기 (0) | 2020.05.22 |
XSS (Cross-site Scripting, 크로스 사이트 스크립팅) 방지 (0) | 2020.05.13 |
QueryDSL multiple subselect - (a,b) in (select c,d) (0) | 2019.04.17 |
MSA (Micro service architecture) vs monolithic (0) | 2019.01.22 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
Comments