1. 소개

웹 서비스를 개발할 때 슬래시를 포함 할 수있는 복잡하거나 예상치 못한 URL 경로를 처리해야 할 수 있습니다 . 결과적으로 사용중인 웹 서버 또는 프레임 워크에 문제가 발생할 수 있습니다.

Spring은 제공하는 기본 구성으로 인해 이와 관련하여 약간 까다로울 수 있습니다.

이 예제에서는 Spring에서 슬래시가있는 URL을 처리하기위한 몇 가지 일반적인 솔루션과 권장 사항을 보여줍니다 . 또한 이러한 문제를 해결하기 위해 몇 가지 일반적인 해킹을 사용하지 않아야하는 이유도 알아 봅니다. 그것에 대해 더 알고 싶다면 계속 읽으십시오!

2. 수동으로 요청 구문 분석

웹 서비스에서 때때로 특정 경로 아래의 모든 요청을 동일한 엔드 포인트에 매핑해야합니다. 설상가상으로 나머지 경로가 어떻게 생겼는지 알 수 없습니다. 나중에 사용하기 위해이 경로를 매개 변수로 수신해야 할 수도 있습니다.

/ mypaths 아래의 모든 경로로 요청을받을 수 있다고 가정 해 보겠습니다 .

http://localhost:8080/mypaths/any/custom/path

그리고 우리가 어떤 요청을 받고 있는지 알기 위해 이러한 모든 다른 경로를 데이터베이스에 저장한다고 가정합니다.

우리 마음에 떠오를 첫 번째 해결책은 경로의 동적 부분을 PathVariable 로 캡처하는 것입니다 .

@GetMapping("mypaths/{anything}")
public String pathVariable(@PathVariable("anything") String anything) {
    return anything;
}

불행히도 PathVariable 에 슬래시가 포함되어 있으면 404반환 된다는 것을 곧 알게됩니다 . 슬래시 문자는 URI 표준 경로 구분 기호이며 그 뒤에 오는 모든 문자는 경로 계층 구조에서 새 수준으로 계산됩니다. 예상대로 Spring은이 표준을 따릅니다.

** 와일드 카드 를 사용하여 특정 경로의 모든 요청에 ​​대한 폴백을 생성하여이 문제 를 쉽게 해결할 수 있습니다 .

@GetMapping("all/**")
public String allDirectories(HttpServletRequest request) {
    return request.getRequestURI()
        .split(request.getContextPath() + "/all/")[1];
}

그런 다음 관심있는 경로의 일부를 얻기 위해 URI를 직접 구문 분석해야합니다.

이 솔루션은 URL과 유사한 매개 변수로 작업 할 때 매우 편리 하지만 다음 섹션에서 볼 수 있듯이 다른 경우에는 충분하지 않습니다.

3. 쿼리 매개 변수 사용

이전 예제와 달리 다른 경로를 매핑하는 것뿐만 아니라 URL의 매개 변수로 문자열받는 다른 경우가 있습니다.

이전 예에서 연속적인 슬래시를 포함하는 경로 매개 변수를 사용 하여 요청을 한다고 가정 해 보겠습니다 .

http://localhost:8080/all/http://myurl.com

처음에는 이것이 작동한다고 생각할 수 있었지만 컨트롤러가 http : /myurl.com을 반환한다는 것을 곧 알게 됩니다. 이는 Spring Security가 URL을 정규화하고 이중 슬래시를 단일 슬래시로 대체 하기 때문에 발생 합니다 .

Spring은 또한 경로 순회와 같은 URL의 다른 시퀀스를 정규화합니다. 공식적인 Spring Security 문서에 설명 된 것처럼 악성 URL이 정의 된 Security 제약을 우회하는 것을 방지하기 위해 이러한 예방 조치 합니다 .

이러한 경우 대신 쿼리 매개 변수를 사용하는 것이 좋습니다.

@GetMapping("all")
public String queryParameter(@RequestParam("param") String param) {
    return param;
}

이렇게하면 이러한 Security 제한없이 모든 문자열 매개 변수를 수신 할 수 있으며 웹 서비스가 더욱 강력하고 안전 해집니다.

4. 해결 방법 피하기

우리가 제시 한 솔루션은 매핑 디자인의 일부 변경을 의미 할 수 있습니다. 이로 인해 URL에서 슬래시를 수신 할 때 원래 엔드 포인트가 작동하도록 몇 가지 일반적인 해결 방법을 사용하고 싶을 수 있습니다.

가장 일반적인 해결 방법은 경로 매개 변수에 슬래시를 인코딩하는 것입니다. 그러나 과거에 일부 Security 취약성 이보고되었으며 대부분의 웹 및 애플리케이션 서버 는 기본적으로 인코딩 된 슬래시를 허용하지 않음으로써 이에 대응 했습니다 . Tomcat 과 같이 해당 설정을 변경하는 것만으로도이 동작을 변경할 수 있습니다 .

아파치 서버 와 같은 다른 사람들 은 조금 더 나아가서 인코딩 된 슬래시를 디코딩하지 않고 허용하는 옵션을 도입하여 경로 구분자로 해석되지 않도록했습니다. 어쨌든 이것은 권장되지 않으며 잠재적 인 Security 위험을 초래할 수 있습니다.

반면에 웹 프레임 워크는 몇 가지 예방 조치를 취합니다. 이전에 보았 듯이 Spring은 덜 엄격한 서블릿 컨테이너에 대한 보호로 몇 가지 메커니즘을 추가합니다 . 따라서 서버에서 인코딩 된 슬래시를 허용하는 경우에도 Spring에서 허용해야합니다.

마지막으로 Spring이 기본적으로 제공하는 URI 정규화를 변경하는 것과 같은 다른 종류의 해결 방법이 있습니다. 이전과 마찬가지로 이러한 기본값을 변경하는 경우 매우주의해야합니다.

5. 결론

이 짧은 기사에서는 Spring의 URL에서 슬래시를 처리하는 몇 가지 솔루션을 보여주었습니다. 또한 Spring과 같은 서버 또는 프레임 워크의 기본 구성을 변경하면 발생할 수있는 몇 가지 Security 문제를 소개했습니다.

일반적으로 쿼리 매개 변수는 URL에서 슬래시를 처리하는 가장 좋은 솔루션입니다.

항상 그렇듯이 예제의 전체 소스 코드는 GitHub에서 사용할 수  있습니다 .