kkokkio - 프로젝트/트러블슈팅

JwtAuthenticationFilter에서 엔드포인트 허용 문제

파란배개 2025. 6. 16. 09:29

이전 포스트: SecurityConfig 엔드포인트 권한 설정

문제 개요

오류 상황과 영향 범위 (예: 특정 코드 실행 시 발생, 특정 라이브러리 버전 호환 문제 등) 발생 배경 (예: 코드 테스트 중, 배포 중 문제 발견 등)

오류 상황과 영향 범위

  • JwtAuthenticationFilter 적용 후 인증/인가 설정 과정에서 로그인 후 댓글 작성, 수정, 삭제, 좋아요 등의 특정 엔드포인트만 허용하려 했으나, 다른 API 경로까지 접근이 차단되는 문제가 발생

발생 배경

  • JwtAuthenticationFilter 및 SecurityConfig 설정 중 JWT 기반 인증 및 인가 기능을 테스트하는 과정에서 특정 엔드포인트가 예상치 않게 차단된 문제 발견

오류 메시지 및 원인 분석

오류 코드, 오류 메시지 포함 HTTP 상태 코드, 애플리케이션 로그, 서버 로그 등 구체적인 오류 정보 정리 및 로그 메시지를 통한 분석 제공 문제 발생 원인에 대한 심층 분석

오류 코드 및 메시지

{
    "timestamp": "2025-05-05T02:49:02.048+00:00",
    "status": 401,
    "error": "Unauthorized",
    "path": "/api/v1/posts/2/comments"
}

분석 과정

  • JwtAuthenticationFilter 적용으로 인해, 설정하지 않은 엔드포인트에 대해서도 인증 및 인가 로직이 동작하여 모든 요청에 대해 일괄적으로 차단되는 현상이 발생하였다.
  • SecurityConfig의 authorizeHttpRequests 설정에서 잘못된 경로 지정으로 인해 필터링이 예상대로 동작하지 않았다.

해결 및 고민 과정

처음 문제를 접했을 때 고려했던 대안들과 선택하지 않은 이유 실험적으로 적용한 방법이 실패한 사례와 그 이유 여러 해결책 중 최적의 방안을 선택한 과정

초기 고려한 대안

  • SecurityConfig의 authorize 설정 경로를 명확하게 분리하여 지정
  • JwtAuthenticationFilter의 shouldNotFilter 메소드를 세부적으로 조정하여 특정 경로 제외

최종 해결책 및 구현

문제 해결을 위한 단계별 조치 방법과 코드 예시 (예: 특정 애노테이션 추가, 라이브러리 버전 조정, 설정 변경 등) 참고 자료 (관련 공식 문서, 개발자 커뮤니티 게시물 등)

// 엔드포인트별 권한 설정
			.authorizeHttpRequests(authorize ->
authorize
					// 모든 HTTP 메소드에 대해 인증 없이 접근 가능한 경로
					.requestMatchers(getPublicEndpoints().toArray(String[]::new)
					).permitAll()

					// 댓글 GET 요청 허용
					.requestMatchers(HttpMethod.GET, "/api/v1/posts/*/comments")
					.permitAll()

					// 회원 권한
					.requestMatchers(getPubliCUserEndpoints().toArray(String[]::new)).hasRole("USER")
					// 관리자 권한
					.requestMatchers(getPublicAdminEndpoints().toArray(String[]::new)).hasRole("ADMIN")
					// 그 외 모든 요청 허용
					.anyRequest().permitAll()
			);

기존 권한 설정에서

// 엔드포인트별 권한 설정
			.authorizeHttpRequests(authorize ->
				authorize
					// — USER 로그인 필요
					.requestMatchers(HttpMethod.POST, "/api/v1/posts/*/comments").authenticated()
					.requestMatchers(HttpMethod.PATCH, "/api/v1/comments/*").authenticated()
					.requestMatchers(HttpMethod.DELETE, "/api/v1/comments/*").authenticated()
					.requestMatchers(HttpMethod.POST, "/api/v1/comments/*/like").authenticated()

					// 그 외 모든 요청 허용
					.anyRequest().permitAll()
			);

방식으로 권한 설정 수정 후 JwtAuthenticationFilter에서

// 필터 체인 통과
	@Override
	protected boolean shouldNotFilter(HttpServletRequest request) {
		String path = request.getServletPath();
		String method = request.getMethod();

		// Auth 관련 엔드포인트 ⇒ 무조건 스킵
		if (List.of(
			"/api/v1/auth/login",
			"/api/v1/auth/signup",
			"/api/v1/auth/refresh"
		).contains(path)) {
			return true;
		}

		// “댓글 쓰기·수정·삭제·좋아요” 만 필터 적용
		boolean isCommentWriteEndpoint =
			("POST".equals(method) && path.matches("^/api/v1/posts/\\\\d+/comments$"))            // 댓글 작성
				|| ("PATCH".equals(method) && path.matches("^/api/v1/comments/\\\\d+$"))          // 댓글 수정
				|| ("DELETE".equals(method) && path.matches("^/api/v1/comments/\\\\d+$"))         // 댓글 삭제
				|| ("POST".equals(method) && path.matches("^/api/v1/comments/\\\\d+/like$"));     // 댓글 좋아요

		// isCommentWriteEndpoint 이면 필터 동작(= false 리턴), 아니면 스킵(= true 리턴)
		return !isCommentWriteEndpoint;
	}

에 대한 내용을 추가하여 필터 적용을 함

결과 및 성능 분석

개선 후 응답 속도, DB 부하 감소 수치 등 구체적인 데이터 포함 문제 해결 전/후 성능 비교 그래프나 로그 분석 내용 포함 이슈 트래킹 및 자동화 방안 추가 (내부 개발자가 반복적인 문제 해결을 효율적으로 관리할 수 있도록 가이드 제공)

개선 후 결과

  • 의도한 엔드포인트만 인증 및 인가가 요구되고 나머지 API 경로는 정상적으로 접근 가능하게 설정됨.

추가 개선점

유사한 문제를 방지하기 위한 주의할 점 (예: 애노테이션 명시 여부, 프레임워크 업데이트 주기 확인 등) 문제 해결 과정에서 배운 점 및 중요한 교훈 공유 보안 고려 사항 추가 (해결 과정에서 발생할 수 있는 보안 리스크 및 예방 조치 포함)

주의할 점

  • Spring Security 설정 시 requestMatchers 경로 및 순서의 정확한 관리 필요
  • JwtAuthenticationFilter 적용 범위를 최소한으로 제한하여 불필요한 인증 로직 수행 방지

보안 고려 사항

  • 인증이 불필요한 경로는 명확히 설정하여 보안 취약점 발생 가능성을 최소화하고, 모든 설정 변경은 철저한 보안 리뷰 과정을 거쳐야 한다.