fix(security): P0 — CSRF 방어, h2-console prod 격리, CORS 외부화

- CSRF: CookieCsrfTokenRepository(이중제출 토큰) + SPA용 CsrfTokenRequestAttributeHandler,
  CsrfCookieFilter로 XSRF-TOKEN 쿠키 강제 렌더. /api/auth/login·/api/public/** 는 예외.
  프론트 api.ts가 변경요청에 X-XSRF-TOKEN 헤더 자동 주입.
- 세션쿠키 SameSite=Lax·HttpOnly, prod는 Secure=${ACS_COOKIE_SECURE:false}(HTTPS 시 활성).
- h2-console permitAll·frameOptions.sameOrigin을 spring.h2.console.enabled에 연동 → prod 자동 비노출.
- CORS allowed-origins를 acs.cors.allowed-origins 프로퍼티로 외부화(prod 기본 빈 값, nginx 동일출처).
- .env.example·docker-compose에 ACS_CORS_ALLOWED_ORIGINS·ACS_COOKIE_SECURE 추가.

검증: 빌드/테스트 통과, curl로 CSRF 차단(403)·토큰 통과(404)·로그인/공개 예외·dev h2-console 확인.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
unknown
2026-07-03 09:54:55 +09:00
parent b3f1d5ebb2
commit d15ffe3fce
7 changed files with 130 additions and 25 deletions

View File

@@ -28,6 +28,9 @@ services:
ACS_SMS_PROVIDER: ${ACS_SMS_PROVIDER:-dev}
ACS_SMS_API_URL: ${ACS_SMS_API_URL:-http://210.104.132.59:8000}
ACS_PUBLIC_BASE_URL: ${ACS_PUBLIC_BASE_URL:-http://localhost}
# Security: CORS origins (empty = same-origin via nginx); cookie Secure (enable under HTTPS)
ACS_CORS_ALLOWED_ORIGINS: ${ACS_CORS_ALLOWED_ORIGINS:-}
ACS_COOKIE_SECURE: ${ACS_COOKIE_SECURE:-false}
depends_on:
- db
networks: