한화시스템 SW BEYOND CAMP 22기 24 주차 회고록

chanjin·2026년 4월 13일

작업 기간

2026.04.16 (월) ~ 2026.04.12 (일)


주요 작업

1. 헤더 위조 취약점 제거 — X-User-Id → JWT 서명 검증 전환

배경
기존엔 Gateway가 JWT 검증 후 X-User-Id 헤더를 주입하는 방식이었다. 하지만 내부 네트워크에서 헤더를 임의로 조작하면 다른 사용자로 위장이 가능한 구조였다.

변경 내용
Activity 서비스의 5개 컨트롤러 전체에서 @RequestHeader("X-User-Id")를 @AuthenticationPrincipal Jwt로 교체했다. JWT의 sub 클레임에서 userId를 추출하므로 RS256 서명이 검증된 토큰만
신뢰한다.

Before
 public ResponseEntity<?> createActivity(@RequestHeader("X-User-Id") Long userId, ...)
 After
  public ResponseEntity<?> createActivity(@AuthenticationPrincipal Jwt jwt, ...) {
      Long userId = Long.parseLong(jwt.getSubject());

  변경 대상: ActivityCommandController, ActivityPackageCommandController, ContactCommandController, EmailLogCommandController, ActivityPackageQueryController

2. Swagger UI Bearer 자동 인증

Auth/Activity 서비스 모두 OpenApiConfig에 SecurityScheme(bearerAuth)와 글로벌 SecurityRequirement를 추가했다. Authorize 버튼에 토큰 한 번만 입력하면 모든 API 호출에 자동으로 Bearer
헤더가 붙는다. 운영(prod)에서는 springdoc 자체가 비활성화되어 외부 노출 없음.


3. Auth 서비스 TokenResponse 개선

프론트엔드 헤더에 사용자 정보를 표시하기 위해 로그인 응답(TokenResponse.UserInfo)에 employeeNo, userEmail 필드를 추가했다.


4. HATEOAS 응답 통일 (월요일)

Auth 서비스 사용자 목록 조회 응답을 PagedResponse에서 PagedModel<EntityModel>로 전환해 전체 백엔드 서비스의 응답 형식을 HATEOAS로 통일했다.


트러블슈팅

Swagger 401 문제

로컬 테스트 중 Auth Swagger에서 로그인 시 401이 계속 떴다. 로그를 보니 IllegalArgumentException: 사용자를 찾을 수 없습니다가 발생했고, Spring Boot가 /error로 포워딩할 때 해당 경로가
permitAll() 목록에 없어 인증 없음 → 401이 반환되는 구조였다. 실제 원인은 테스트 데이터의 이메일 불일치였다.

Activity 서비스 JWT 검증 실패

Activity 서비스의 JWKS URI 기본값이 http://backend-auth:8011(Docker 내부 호스트)로 설정되어 있어 로컬 실행 시 JWT 검증 자체가 불가능했다. 로컬 테스트 시엔
JWKS_URI=http://localhost:8011/.well-known/jwks.json 환경변수로 오버라이드해서 해결했다.


느낀 점

X-User-Id 헤더 방식은 MSA 초기에 빠르게 붙이기 좋지만, 내부 신뢰 경계가 무너지면 바로 취약점이 된다. JWT를 각 서비스에서 직접 검증하는 방식이 구현 비용은 조금 더 들어도 훨씬
안전하다. 또 로컬 개발 환경과 Docker 배포 환경의 호스트명 차이를 환경변수로 분리하는 것이 중요하다는 걸 다시 체감했다.

profile
찬지니에오

0개의 댓글