snp-global/src/main/java/com/snp/batch/global/config/BypassAuthenticationEntryPoint.java
HYOJIN b2b268f1e5 chore: 프로젝트 초기 설정 및 팀 워크플로우 구성
- Spring Boot 3.2.1 + React 19 프로젝트 구조
- S&P Global Maritime API Bypass 및 Risk & Compliance Screening 기능
- 팀 워크플로우 v1.6.1 적용 (settings.json, hooks, workflow-version)
- 프론트엔드 빌드 (Vite + TypeScript + Tailwind CSS)
- 메인 카드 레이아웃 CSS Grid 전환

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:42:23 +09:00

57 lines
2.5 KiB
Java

package com.snp.batch.global.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
import java.util.Map;
/**
* Basic Auth 인증 실패 시 계정 상태에 따라 구체적인 오류 정보를 JSON으로 반환하는 EntryPoint.
*
* <ul>
* <li>LockedException (accountLocked=true, 즉 SUSPENDED): ACCOUNT_SUSPENDED</li>
* <li>DisabledException (disabled=true, 즉 비활성/기간 만료): ACCOUNT_DISABLED</li>
* <li>그 외 (잘못된 자격증명 등): INVALID_CREDENTIALS</li>
* </ul>
*
* WWW-Authenticate 헤더를 유지하여 Swagger UI의 Basic Auth 다이얼로그와 호환성을 보장한다.
*/
public class BypassAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
// WWW-Authenticate 헤더를 보내지 않음 — 브라우저 네이티브 로그인 다이얼로그 방지
// Swagger UI는 자체 Authorize 메커니즘으로 Basic Auth를 처리함
String error;
String message;
if (authException instanceof LockedException) {
error = "ACCOUNT_SUSPENDED";
message = "정지된 계정입니다. 관리자에게 문의하세요.";
} else if (authException instanceof DisabledException) {
error = "ACCOUNT_DISABLED";
message = "비활성화된 계정입니다. 접근 기간이 만료되었거나 계정이 비활성 상태입니다.";
} else {
error = "INVALID_CREDENTIALS";
message = "사용자명 또는 비밀번호가 올바르지 않습니다.";
}
objectMapper.writeValue(response.getOutputStream(),
Map.of("error", error, "message", message));
}
}