본문으로 건너뛰기
개발 머꼬
개발 노트Spring
hohyeon.dev18

Spring Security 설정을 추가했는데 특정 API만 계속 401이 난 이유

  • #Auth
  • #Engineering Note
  • #Spring
  • #Spring Security

문제 발생

/api/public/**은 인증 없이 열어두고 싶어서 규칙을 추가했는데, 여전히 401 Unauthorized가 반환됐습니다.

http.authorizeHttpRequests(auth -> auth
    .requestMatchers("/api/**").authenticated()      // 먼저 선언됨
    .requestMatchers("/api/public/**").permitAll()    // 이 규칙은 절대 도달 안 함
);

원인 분석

Spring Security의 authorizeHttpRequests는 등록된 규칙을 선언된 순서대로 검사하고, 가장 먼저 매치되는 규칙을 적용합니다. /api/**/api/public/**보다 먼저 선언되어 있으면, /api/public/health 같은 요청도 /api/** 패턴에 먼저 매치되어 authenticated() 규칙이 적용되고, 그 아래 있는 /api/public/** 규칙은 아예 검사되지도 않습니다.

이건 마치 switch문이나 여러 개의 if-else if가 위에서부터 순서대로 평가되는 것과 같은 원리입니다 — 더 넓은 패턴이 먼저 있으면 더 좁은(구체적인) 패턴이 실행될 기회를 얻지 못합니다.

해결 방안

  1. 더 구체적인 경로 규칙을 먼저, 더 일반적인 규칙을 나중에 선언합니다.
http.authorizeHttpRequests(auth -> auth
    .requestMatchers("/api/public/**").permitAll()    // 구체적인 규칙 먼저
    .requestMatchers("/api/**").authenticated()        // 일반적인 규칙 나중
);
  1. 규칙이 많아지면 순서 실수가 반복되기 쉬우므로, 테스트 코드로 각 경로의 실제 접근 가능 여부를 검증해두는 것이 안전합니다 — @WithMockUser, MockMvc를 활용한 보안 설정 테스트가 표준적인 방법입니다.
  2. Spring Security 자체의 FilterChain 순서(여러 개의 SecurityFilterChain을 등록하는 경우)도 마찬가지로 순서에 민감합니다 — @OrdersecurityMatcher()로 어느 체인이 어떤 요청에 적용될지 명확히 분리해야 합니다.
  3. 규칙을 다 작성한 뒤에는 실제로 각 경로에 인증 없이/있이 요청을 보내 예상대로 동작하는지 직접 확인하는 것이 코드만 보고 판단하는 것보다 확실합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.