servlet filter 사용시의 @ModelAttribute

2,656 views
Skip to first unread message

개발자 용이

unread,
Jun 7, 2011, 3:22:04 AM6/7/11
to Korea Spring User Group
안녕하세요. 매일 눈팅만하다가 처음으로 질문하나 올립니다;;

서블릿필터를 이용하여 파라메터값을 변경하였을 때 @ModelAttribute 어노테이션이 붙은 녀석들이 서블릿필터를 타기전의
파라메터 값으로 나오는군요.. xss, sql injection 처리부분을 servlet filter 를 써서 구현하던중...
ㅠ.ㅠ request.getParameter() 메소드를 이용하여 로그를 찍어보면 잘 나오구 있고...

마찬가지로 @RequesrParam 어노테이션을 붙였을 때에도 동일하게 서블릿필터를 타기전의 파라메터 값으로 나옵니다.

혹시 저처럼 애먹으신분 안계신가요?? 조언 좀 부탁드립니다.

참고로 spring 버전은 3.0 입니다.

이재일

unread,
Jun 7, 2011, 9:57:37 PM6/7/11
to ks...@googlegroups.com
web.xml, servlet-context.xml 올려주세요.  그밖에 근거자료가 좀더 있어야 알겠네요.

2011년 6월 7일 오후 4:22, 개발자 용이 <yoy...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


Sanghyuk Jung

unread,
Jun 8, 2011, 5:54:23 AM6/8/11
to ks...@googlegroups.com
ServletFilter 소스가 있으면 참조가 될 것 같아요.
 
전에 비슷하게 ServletFilter에서 XssFiltering했을 때 문제없이 잘 되었는데, 적용방식이 다른 점이 있는지 모르겠네요~

2011년 6월 8일 오전 10:57, 이재일 <son...@gmail.com>님의 말:

개발자 용이

unread,
Jun 8, 2011, 11:36:12 PM6/8/11
to Korea Spring User Group
일단 web.xml 에서는

<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-
class>org.springframework.web.filter.CharacterEncodingFilter</filter-
class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>parameterFilter</filter-name>
<filter-class>com.xxx.filter.ParameterFilter</filter-class>
<init-param>
<param-name>configureFileName</param-name>
<param-value>parameterFilter.properties</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>parameterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

두개의 서블릿 필터가 등록 되어있습니다. 초기화 파라메터로 parameterFilter.properties 를 넘기는데 여기서
는 치환하지 말하야할 url 과 파라메터명들이 들어있어고 해당 url 의 해당 파라메터는 필터쪽에서 치환하지 않고 원본 파라메터
를 보내주도록 구현이 되어있습니다.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/com/xxx/spring/root-context.xml</param-
value>
</context-param>

root-context.xml 의 내용은 요약하면 밑의 내용과 같구요.

<!-- Business Logic -->
<import resource="applicationContext-service.xml" />

<!-- Aspect (AOP) -->
<import resource="applicationContext-aspect.xml" />


또 디스패처쪽 설정은 밑에 처럼 되어있습니다.
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</
servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/com/xxx/spring/servlet/dispatcher.xml</
param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

서블릿 필터의 doFilter 메소드에서는 HttpServletRequestWrapper 를 상속받아 구현한
requestWrapper 를 받아서
filterChain.doFilter(requestWrapper, response); 와 같이 넘겨 주고 있습니다.

getParameter(), getParameterValues(), getParameterMap() 메소드는 오버라이드 하여 치
환하도록 되어있습니다.

밑에는 getParameter() 메소드의 요약내용입니다. StringUtil.replaceHTMLTag() 요 넘이 치환하는
놈이구요. getParameterValues(), getParameterMap() 메소드도 거의 동일한 방식으로 구현되어있습니
다.

public String getParameter(String name) {
return StringUtil.replaceXss(super.getParameter(name));
}

request.getClass().getName() 을 찍어보면 제가 구현한 wrapperRequest 로 나오고 있고, 문제
는 jsp 부분과 컨트롤러쪽에서 request.getParameter(), getParameterValues(),
getParameterMap() 메소드를 호출한 경우 치환된 값이 잘 나오는데...

컨트롤러쪽 메소드에서 @ModelAttribute, @RequesrParam 를 썼을 경우, 치환전의 값으로 나오고 있다는 겁니
다 ㅠ.ㅠ

스프링쪽에서 parameter 값들을 @ModelAttribute, @RequesrParam 에 넣어줄 때 치환되기전의 원본
request 로 하고있는걸까요? 아니면 requestWrapper 부분에서 request 를 파싱하는 부분을 다시 만들어야하는
걸까요...

Sanghyuk Jung

unread,
Jun 9, 2011, 6:29:48 PM6/9/11
to ks...@googlegroups.com

 전에 어떤 프로젝트에서 Filter에서 HttpServletRequest의 Wrapper를 만들어서 잘 안되었다가,  아래와 유사하게 getParameterMap안에 있는 스트링배열(String[])의 요소를 바꿔치기 하니 잘 돌아갔다는 이야기를 들은적이 있습니다.


@SupressWarnings(“unchecked”)
Map<String,String[]> params = request.getParameterMap();

for(String[] values : params.values()){
  for (int i = 0, n = values.length; i < n; i++) {
     values[i] = StringUtil.replaceXss(values[i]);
   }
}

 getValues말고 entrySet을 이용해서도 할수 있겠죠.
for(Entry<String,String[]> entry :  request.getParameterMap().entrySet() ) {
 String[] values =  entry.getValue() 
...
}

 HttpServletRequest를 상속해서 구현하면 상위클래스에서 getParameter, getParameterValues, getParameterMap간의 내부 의존 관계가 있는지 등도 신경써야해서, 예상밖으로 동작할 가능성이 더 커질 것 같습니다. 



2011년 6월 9일 오후 12:36, 개발자 용이 <yoy...@gmail.com>님의 말:

--

Jaeyong Kim

unread,
Jun 10, 2011, 2:03:18 AM6/10/11
to ks...@googlegroups.com, Sanghyuk Jung

답변 감사드립니다.

현재 스프링 3.0.5 기준으로 @ModelAttribute 를 썼을 때에 request.getParameterValues() 메소드를 호출하는군요. 

제가 만든  requestWrapper class 쪽에 getParameterValues() 오버라이드 한 부분에 일단 이상이 있었습니다.

일단 일반 request 는 해결이 되었습니다.

문제는 이제 멀티파트 request 네요.

멀티파트일 경우에는 컨트롤러에서 request 의 클래스를 찍어보니 

class org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest 로 나오네요.

멀티파트쪽 문제 해결되면 공유하도록 하겠습니다.


2011. 6. 10., 오전 7:29, Sanghyuk Jung 작성:

Sanghyuk Jung

unread,
Jun 10, 2011, 3:45:53 AM6/10/11
to Jaeyong Kim, ks...@googlegroups.com
네, filter 안에서 직접 String[]을 replace하는 방법보다는 HttpServletRequest를 상속해서 override하는 방식을 계속 쓰시기로했나보네요.
그런데 httpServletRequest.getParametersMap.values의 String[]을 바뀌치기하는 것도 서플릿스펙에서 보장되는 방식인지는 모르겠습니다. Tomcat에서는 되었는데 다른 WAS에서는 어떨지는 모르겠네요.

참고로 XssFilter에 대해서 유사한 질문이 KSUG에 2번정도 올라왔었는데, 참조해보실만도 합니다.




2011년 6월 10일 오후 3:03, Jaeyong Kim <yoy...@gmail.com>님의 말:

Jaeyong Kim

unread,
Jun 10, 2011, 4:20:54 AM6/10/11
to Sanghyuk Jung, ks...@googlegroups.com
감사합니다. 덕분에 많은 도움이 되었습니다.

멀티파트쪽도 간단하게 해결되었습니다. 

스프링쪽의 org.springframework.web.multipart.support.MultipartFilter 를 제가만든 서블릿필터의 앞쪽에 놓았더니 간단하게 해결되네요.

내용은 다음과 같습니다.

web.xml 
  
   ....
  <filter>
    <filter-name>multipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    <init-param>
      <param-name>multipartResolverBeanName</param-name>
      <param-value>multipartResolver</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>multipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
   ....
   여기에는 제가 구현한 필터가 들어갑니다.
   

multipartFilter 의 초기화 파라메터로 multipartResolverBeanName 에다가 스프링 멀티파트리졸버를 추가해주면됩니다.


위에처럼 멀티파트 필터 등록을 안하고 있을 때는 스프링에서 파싱한 멀티파트가 제가 작성한 서블릿 필터를 탄 후에 언젠가 타고나서 파싱을 하고있었던거 같은데 위에처럼하니 먼저 멀티파트쪽 파싱후 제 필터로 넘어와서 그런지 parameter 부분도 제가 원했던것 처럼 치환해서 잘 가져오고있네요.

2011. 6. 10., 오후 4:45, Sanghyuk Jung 작성:
Reply all
Reply to author
Forward
0 new messages