트러블슈팅-requestmatcher
Spring security가 허용된 경로를 차단하는 문제
분명 security filter의 filterChain 메서드에서
.requestMatchers("/api/auth/**","/api/users").permitAll()
과 같이 authentication을 받지 않는 경로를 적어주었는데 계속해서 403을 반환하며 security에서 회원가입 요청을 차단했다. 이런저런 시도를 하다 결국 문제를 발견했는데
application.properties에서 context-path로 /api를 뺀 것이 문제였다.
이런 문제가 발생하는 이유는 스프링의 작동 구조 때문이다.
이름에서도 알 수 있듯이 spring security는 filter를 기반으로 작동한다. 하지만 Spring Security의 필터는 DispatcherServlet
이전에 실행된다. 따라서 Spring Security는 전체 URL 경로를 볼 수 있지만, context-path가 적용되기 전의 경로를 보게 된다. 즉
"/api/auth/**","/api/users"
가 아닌 "/auth/**","/users"
를 보게 되는 것이다.
작동 순서는 다음과 같다.
- 요청 흐름: 클라이언트 → Nginx → Tomcat → 필터(Spring Security) → DispatcherServlet → 컨트롤러
- 클라이언트 요청:
http://localhost:8080/api/users
- 클라이언트(브라우저)가 Nginx로 요청을 보냅니다.
-
Nginx 프록시 처리:
location /api/ { proxy_pass http://localhost:8081/api/; # Spring Boot 서버로 전달 }
- Nginx는 이 요청을
http://localhost:8081/api/users
로 프록시합니다. - 원본 URL 구조를 유지하며 백엔드 서버로 전달합니다.
- Nginx는 이 요청을
- Spring Boot 서버(WAS) 수신:
- Tomcat(또는 다른 서블릿 컨테이너)이
http://localhost:8081/api/users
요청을 받습니다. - 이 시점에서 URL은 여전히 원본 형태입니다.
- Tomcat(또는 다른 서블릿 컨테이너)이
- 서블릿 컨텍스트 경로 처리:
- Spring Boot 애플리케이션에
server.servlet.context-path=/api
설정이 있으면, - 서블릿 컨테이너는
/api
를 컨텍스트 경로로 인식합니다. - 요청 URL에서 컨텍스트 경로(
/api
)를 식별하고 내부적으로 요청 처리를 위한 매핑을 준비합니다.
- Spring Boot 애플리케이션에
- 필터 체인 처리 (Spring Security 포함):
- Spring Security 필터가 요청을 수신할 때, 서블릿 컨테이너는 이미 컨텍스트 경로를 인식했지만 아직 제거하지는 않은 상태입니다.
- 중요: Spring Security의
.requestMatchers()
는 내부적으로 컨텍스트 경로를 고려하여 매칭합니다. - 즉,
.requestMatchers("/users")
는 실제로/api/users
와 매칭됩니다.
- DispatcherServlet으로 전달:
- 필터 체인을 통과한 후, 요청은 DispatcherServlet으로 전달됩니다.
- 이 시점에서 서블릿 컨테이너는 컨텍스트 경로를 제거하고, DispatcherServlet은
/users
만 보게 됩니다.
- 컨트롤러 매핑:
- DispatcherServlet은
/users
경로를 바탕으로 적절한 컨트롤러를 찾습니다. @RequestMapping("/users")
가 이 요청과 매칭됩니다.
- DispatcherServlet은
핵심은 이것이다.
Spring Security 필터는 DispatcherServlet 이전에 실행된다.
- 따라서 Spring Security를 포함한 모든 filter는 원본 URL(
/api/users
)을 그대로 본다.
그러나 .requestMatchers()
를 사용한 URL 패턴 매칭은
- Spring Security가 내부적으로 서블릿 컨테이너의 context-path 설정을 인식하여 매칭 시 자동으로 고려한다.
- 즉 Spring Security는
ApplicationContext
에서 context-path 설정을 읽어와 패턴 매칭에 적용합니다.
어려운 문제가 아닐 수 없다. 이 문제를 겪으며 스프링이 정말 추상화가 잘 되있지만 그만큼 추상화로 인해 내부를 들여다볼 수 없다는 문제를 깨닫게 됐고, 깊이 있는 공부의 중요성을 다시 한번 되새기게 됐다.