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. * * * * 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)); } }