복붙노트

[SPRING] Spring / Rest @PathVariable 문자 인코딩

SPRING

Spring / Rest @PathVariable 문자 인코딩

내가 사용하는 환경 (Tomcat 6)에서 경로 세그먼트의 백분율 시퀀스는 @PathVariable에 매핑 될 때 ISO-8859-1을 사용하여 분명히 디코딩됩니다.

나는 그것이 UTF-8이되기를 바랍니다.

server.xml에서 URIEncoding 속성을 사용하여 UTF-8을 사용하도록 Tomcat을 구성했습니다.

Spring / Rest가 독자적으로 디코딩을하고 있습니까? 그렇다면 기본 인코딩을 대체 할 수있는 위치는 어디입니까?

추가 정보; 여기에 내 테스트 코드 :

@RequestMapping( value = "/enc/{foo}", method = RequestMethod.GET )
public HttpEntity<String> enc( @PathVariable( "foo" ) String foo, HttpServletRequest req )
{
  String resp;

  resp = "      path variable foo: " + foo + "\n" + 
         "      req.getPathInfo(): " + req.getPathInfo() + "\n" +
         "req.getPathTranslated(): " + req.getPathTranslated() + "\n" + 
         "    req.getRequestURI(): " + req.getRequestURI() + "\n" + 
         "   req.getContextPath(): " + req.getContextPath() + "\n";

  HttpHeaders headers = new HttpHeaders();
  headers.setContentType( new MediaType( "text", "plain", Charset.forName( "UTF-8" ) ) );
  return new HttpEntity<String>( resp, headers );
}

다음 URI 경로로 HTTP GET 요청을하면 :

/TEST/enc/%c2%a3%20and%20%e2%82%ac%20rates

UTF-8로 인코딩 된 다음 백분율로 인코딩 된 형식의

/TEST/enc/£ and € rates

내가 얻는 결과는 다음과 같다.

      path variable foo: £ and ⬠rates
      req.getPathInfo(): /enc/£ and € rates
req.getPathTranslated(): C:\Users\jre\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\TEST\enc\£ and € rates
    req.getRequestURI(): /TEST/enc/%C2%A3%20and%20%E2%82%AC%20rates
   req.getContextPath(): /TEST

나에게 URIEncoding 속성을 설정 한 후 Tomcat이 올바른 일을하지만 (getPathInfo () 참조) 경로 변수는 ISO-8859-1에서 여전히 디코딩된다는 것을 보여줍니다.

그리고 그 대답은 :

Spring / Rest는 요청 인코딩을 사용합니다. 이것은 매우 이상한 일입니다. 이것은 URI가 아닌 본문에 관한 것입니다. 한숨.

추가 :

<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>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

문제가 해결되었습니다. 정말 간단해야합니다.

실제로, 그것은 더 나쁩니다.

메소드에 실제로 요청 본문이 있고 UTF-8로 인코딩되지 않은 경우 추가 forceEncoding 매개 변수가 필요합니다. 이것은 효과가있는 것으로 보이지만 나중에 문제가 더 많이 발생할 것이라는 점에 우려하고 있습니다.

또 다른 접근법

그동안 디코딩을 사용하지 않도록 설정할 수 있다는 것을 알았습니다.

<property name="urlDecode" value="false"/>

...받는 사람은 올바른 일을 할 수 있습니다. 물론 이것은 많은 다른 것들을 더 어렵게 만들 것입니다.

해결법

  1. ==============================

    1.web.xml에 필터를 추가해야하는 것

    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>
    
  2. ==============================

    2.문자 인코딩 필터가있는 경우에도 path 변수가 ISO-8859-1에서 여전히 디코드됩니다. 여기이 문제를 해결하기 위해해야 ​​할 일이 있습니다. 다른 아이디어가 있으면 알려주세요!

    문자 인코딩 필터가있는 경우에도 path 변수가 ISO-8859-1에서 여전히 디코드됩니다. 여기이 문제를 해결하기 위해해야 ​​할 일이 있습니다. 다른 아이디어가 있으면 알려주세요!

    서버에서 실제 UTF-8 디코딩 된 문자를 보려면이 작업을 수행하고 값을 살펴보십시오 (컨트롤러 매개 변수에 "HttpServletRequest httpServletRequest"를 추가해야 함).

    String requestURI = httpServletRequest.getRequestURI();
    String decodedURI = URLDecoder.decode(requestURI, "UTF-8");
    

    그런 다음 서버에서 올바른 데이터를 디코딩 했으므로 원하는대로 (디코딩 된 URI에서 매개 변수를 수동으로 가져 오는 것과 같이) 할 수 있습니다.

  3. ==============================

    3.server.xml의 Tomcat에 커넥터를 구성하십시오. useBodyEncodingForURI = "true"또는 URIEncoding = "UTF-8"을 Connector 태그에 추가하십시오. 예 :

    server.xml의 Tomcat에 커넥터를 구성하십시오. useBodyEncodingForURI = "true"또는 URIEncoding = "UTF-8"을 Connector 태그에 추가하십시오. 예 :

        <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               useBodyEncodingForURI="true"
               redirectPort="8443" />
    
  4. ==============================

    4.하지만이 작업을하기 위해 Tomcat 구성 (URIEncoding)을 혼란에 빠뜨리면 안된다. 서블릿 API가 경로를 얻고 매개 변수를 압축 해제 된 표현으로 요청할 수있는 방법을 제공하면 애플리케이션 (또는 Spring)은 자체적으로 디코딩을 완전히 처리 할 수 ​​있습니다. 그리고 분명히, HttpServletRequest # getPathInfo와 HttpServletRequest # getQueryString은 이것을 제공 할 것이지만, 후자의 경우 이것은 Spring이 HttpServletRequest # getParameter와 friends에 의존하지 않고 쿼리 문자열을 해석하고 해독해야한다는 것을 의미합니다. 분명히 그들은 이것을하지 않습니다. 즉, @RequestParam 또는 @PathVariable을 사용하여 servlet 컨테이너의 구성에 의존하지 않고 us-ascii 문자열 이외의 문자열을 안전하게 캡처 할 수 없습니다.

    하지만이 작업을하기 위해 Tomcat 구성 (URIEncoding)을 혼란에 빠뜨리면 안된다. 서블릿 API가 경로를 얻고 매개 변수를 압축 해제 된 표현으로 요청할 수있는 방법을 제공하면 애플리케이션 (또는 Spring)은 자체적으로 디코딩을 완전히 처리 할 수 ​​있습니다. 그리고 분명히, HttpServletRequest # getPathInfo와 HttpServletRequest # getQueryString은 이것을 제공 할 것이지만, 후자의 경우 이것은 Spring이 HttpServletRequest # getParameter와 friends에 의존하지 않고 쿼리 문자열을 해석하고 해독해야한다는 것을 의미합니다. 분명히 그들은 이것을하지 않습니다. 즉, @RequestParam 또는 @PathVariable을 사용하여 servlet 컨테이너의 구성에 의존하지 않고 us-ascii 문자열 이외의 문자열을 안전하게 캡처 할 수 없습니다.

  5. from https://stackoverflow.com/questions/4470787/spring-rest-pathvariable-character-encoding by cc-by-sa and MIT license