package com.takensoft.common.oauth.handler; import com.takensoft.cms.loginPolicy.service.LoginModeService; import com.takensoft.cms.mber.service.LgnHstryService; import com.takensoft.cms.mber.service.UnifiedLoginService; import com.takensoft.cms.mber.vo.LgnHstryVO; import com.takensoft.cms.mber.vo.MberVO; import com.takensoft.common.oauth.vo.CustomOAuth2UserVO; import com.takensoft.common.util.HttpRequestUtil; import com.takensoft.common.util.LoginUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.URLEncoder; /** * @author takensoft * @since 2025.05.22 * @modification * since | author | description * 2025.05.22 | takensoft | 최초 등록 * 2025.05.28 | takensoft | 통합 로그인 적용 * 2025.05.29 | takensoft | OAuth2 통합 문제 해결 * * OAuth2 로그인 성공 핸들러 - 통합 로그인 시스템 적용 (문제 해결) */ @Slf4j @Component @RequiredArgsConstructor public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private final UnifiedLoginService unifiedLoginService; private final LgnHstryService lgnHstryService; private final HttpRequestUtil httpRequestUtil; private final LoginUtil loginUtil; private final LoginModeService loginModeService; @Value("${front.url}") private String frontUrl; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { CustomOAuth2UserVO oAuth2User = (CustomOAuth2UserVO) authentication.getPrincipal(); try { // 현재 설정된 로그인 모드 확인 String currentLoginMode = loginModeService.getLoginMode(); // 통합 로그인 서비스를 통한 OAuth2 사용자 처리 MberVO mber = unifiedLoginService.processOAuth2User( oAuth2User.getEmail(), convertProviderToMbrType(oAuth2User.getProvider()), oAuth2User.getId(), oAuth2User.getName(), request ); saveLoginHistory(request, mber, oAuth2User.getProvider()); // LoginUtil을 통한 통합 로그인 처리 loginUtil.successLogin(mber, request, response); String redirectUrl = String.format("%s/login.page?oauth_success=true&loginMode=%s", frontUrl, currentLoginMode); getRedirectStrategy().sendRedirect(request, response, redirectUrl); } catch (Exception e) { handleOAuth2Error(response, e); } } /** * 로그인 이력 저장 */ private void saveLoginHistory(HttpServletRequest request, MberVO mber, String provider) { try { String userAgent = httpRequestUtil.getUserAgent(request); LgnHstryVO loginHistory = new LgnHstryVO(); loginHistory.setLgnId(mber.getLgnId()); loginHistory.setLgnType(mber.getAuthorities().stream() .anyMatch(r -> r.getAuthority().equals("ROLE_ADMIN")) ? "0" : "1"); loginHistory.setCntnIp(httpRequestUtil.getIp(request)); loginHistory.setCntnOperSys(httpRequestUtil.getOS(userAgent)); loginHistory.setDeviceNm(httpRequestUtil.getDevice(userAgent)); loginHistory.setBrwsrNm(httpRequestUtil.getBrowser(userAgent)); lgnHstryService.LgnHstrySave(loginHistory); } catch (Exception e) { log.error("로그인 이력 저장 실패: {}", e.getMessage()); } } /** * 제공자명을 회원타입으로 변환 */ private String convertProviderToMbrType(String provider) { return switch (provider.toLowerCase()) { case "kakao" -> "K"; case "naver" -> "N"; case "google" -> "G"; case "facebook" -> "F"; default -> "S"; }; } /** * OAuth2 오류 처리 */ private void handleOAuth2Error(HttpServletResponse response, Exception e) throws IOException { String message = URLEncoder.encode("OAuth 로그인에 실패했습니다.", "UTF-8"); String errorUrl = String.format("%s/login.page?error=oauth2_failed&message=%s", frontUrl, message); getRedirectStrategy().sendRedirect(null, response, errorUrl); } }