웹에서 텍스트를 입력받다보면 다음과 같이 입력 필드 (여기서는 설명이라고 적은)에 저렇게 script코드를 넣으면 스크립트 실행이 가능하다.
설명 : [ <script>alert('hello');</script> ]
이걸 막아야지.. 막기위해 가장 좋은 방법은..
&나 <, >등의 특수 기호를 &, <, >등으로 치환하면 된다.
브라우저에서는 그 문자열들을 보고 기호로 다시 복원해주니까.
그러면 이러한 입력이 오는곳 모든 곳 마다 다 문자열 치환하는 코드를 구현한다면? 해결될거같긴 하다.
근데 엄청 비효율적이다. 유틸리티처럼 뽑아낸다 해도, 매번 입력받는 곳 마다 저걸 호출해야할테니까.
다행히, Spring에서는 Filter를 적용할 수 있다. Interceptor도 있지만 우선 URL이 호출되어 먼저 만나는 녀석이 Filter니까.. Filter를 하나 추가하여, 해당 필터에서 문자 치환하면 된다.
public class MyTagFilter implements Filter{
private FilterConfig config;
@Override
public void destroy(){
...
}
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException{
chain.doFilter(new MyTagFilterWrapper((HttpServletRequest)request), response);
}
}
이렇게 필터를 만들고...
근데 무언가 할 일을 하는 애가 안보인다? 치환은 wrapper에서..
그럼 이제 wrapper를 만들자.
public class MyTagFilterWrapper extends HttpServletRequestWrapper{
public MyTagFilterWrapper(HttpServletRequest request){
super(request);
}
@Override
public String getParameter(String parameter){
return this.convertEscape(super.getParameter(parameter));
}
@Override
public String[] getParameterValues(String parameter){
String[] values = super.getParameterValues(parameter);
for( int i = 0 ; i < values.length ; i++){
if( values[i] != null){
values[i] = this.convertEscape(values[i]);
}
}
return values;
}
private String convertEscape(String value){
if( value != null){
StringBuffer sb = new StringBuffer();
for( int i = 0 ; i < value.length() ; i++){
char c = value.charAt(i);
switch(c){
case '<':
sb.append("<");
break;
case '>':
sb.append(">");
break;
...
}
}
value = sb.toString();
}
return value;
}
}
이렇게 치환할 wrapper를 다 만들었으면.. 그 다음은 필터 사용을 등록하자.
filter사용은 web.xml에 추가하면 된다. (다른 필터도 적용할거면 순서를 잘 정의해서 기입하자.)
<filter>
<filter-name>multipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>multipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>MyTagFilter</filter-name>
<filter-class>내패키지이름.MyTagFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>MyTagFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
위에 multipart는 뭐냐고?
해당 multipart가 없으면.. form으로 전송되는 데이터에 대해서는 filter가 적용되지 않는다.
그래서 그걸 위해 저 필터를 먼저 추가한다.
그리고.. multipart를 추가하면 톰캣의 Context.xml (또는 Server.xml)의 Context에 다음 한줄을 추가해주어야한다.
<Context allowCasualMultipartParsing="true">
...
</Context>
allowCasualMultipartParsing="true"를 꼭 해줄것.
댓글