Spring Boot 프로젝트에서 REST API 경로에 공통 prefix(/api)를 적용하기 위해 context-path 설정을 사용하는 경우가 많다.
하지만 이렇게 설정한 뒤, Spring Security에서 특정 경로를 허용하려 할 때, 의도한 대로 매칭되지 않고 403 혹은 401 에러가 발생하는 경우가 있다.
문제 상황
다음과 같이 context-path를 설정하고
server:
servlet:
context-path: /api
그리고 Security 설정에서는 아래와 같이 /api/login을 허용하도록 구성했다
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/login").permitAll()
.anyRequest().authenticated()
);
이 경우
클라이언트에서 /api/login으로 요청을 보내면 403 Forbidden 또는 401 Unauthorized 오류가 발생한다.
원인 분석
Spring Boot에서 server.servlet.context-path는 DispatcherServlet 레벨에서 모든 API 경로 앞에 /api prefix를 붙이게 된다.
예를 들어, 컨트롤러의 매핑이 다음과 같다면:
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
...
}
실제 호출 가능한 경로는 /api/login이 된다.
하지만,
Spring Security는 context-path를 제거한 경로 기준으로 경로 매칭을 수행한다.
즉, requestMatchers("/api/login")는 실제 Security filter chain에서 존재하지 않는 경로로 간주된다.
Spring Security의 경로 매칭은 HttpServletRequest.getServletPath() 기준으로 이루어지며,
이 값은 context-path가 제외된 상태이다.
String servletPath = request.getServletPath(); // "/login"
해결 방법
Security 설정 시 context-path(prefix)를 포함하지 않고 경로를 지정
- 실제 요청은 /api/login이지만,
- Security 설정에서는 /login으로 매칭해야 한다.
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll() // "/api/login" 아님
.anyRequest().authenticated()
);
'Spring > 문제 해결 (Troubleshooting)' 카테고리의 다른 글
@Cacheable 사용 시 역직렬화 오류 해결 (1) | 2025.07.15 |
---|---|
@ControllerAdvice가 Filter 예외를 잡지 못하는 문제 해결 (0) | 2025.06.04 |
Spring Security 에러 핸들링 오류 해결, /error 접근 권한 문제 (0) | 2025.05.29 |
@LastModifiedDate 와 DB의 ON UPDATE CURRENT_TIMESTAMP 동시 사용 문제 (1) | 2025.05.23 |
JPA 변경사항이 즉시 반영되지 않을 때 - 영속성 컨텍스트와 DB 값 불일치 문제 (2) | 2025.05.23 |