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.
*
*
* - LockedException (accountLocked=true, 즉 SUSPENDED): ACCOUNT_SUSPENDED
* - DisabledException (disabled=true, 즉 비활성/기간 만료): ACCOUNT_DISABLED
* - 그 외 (잘못된 자격증명 등): INVALID_CREDENTIALS
*
*
* 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));
}
}