package com.takensoft.common.oauth.handler; import com.takensoft.cms.loginPolicy.service.LoginModeService; import com.takensoft.cms.loginPolicy.service.LoginPolicyService; import com.takensoft.cms.mber.service.LgnHstryService; import com.takensoft.cms.mber.service.UnifiedLoginService; import com.takensoft.cms.mber.service.Impl.UnifiedLoginServiceImpl; import com.takensoft.cms.mber.vo.MberVO; 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 통합 문제 해결 * 2025.06.02 | takensoft | 세션 모드 중복로그인 처리 개선 * 2025.06.09 | takensoft | OIDC 타입 캐스팅 문제 해결 * 2025.06.18 | takensoft | OAuth 사용자 정보 추출 및 로그인 이력 저장 로직 통합 * * OAuth2 로그인 성공 핸들러 - 최종 중복 제거 완료 */ @Slf4j @Component @RequiredArgsConstructor public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private final UnifiedLoginService unifiedLoginService; private final LgnHstryService lgnHstryService; private final LoginUtil loginUtil; private final LoginModeService loginModeService; private final LoginPolicyService loginPolicyService; @Value("${front.url}") private String frontUrl; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { try { // 통합된 사용자 정보 추출 로직 사용 UnifiedLoginServiceImpl.OAuth2UserInfo userInfo = extractUserInfo(authentication); if (userInfo == null) { handleOAuth2Error(response, new Exception("사용자 정보 추출 실패")); return; } // 현재 설정된 로그인 모드 확인 String currentLoginMode = loginModeService.getLoginMode(); boolean allowMultipleLogin = loginPolicyService.getPolicy(); // 통합 로그인 서비스를 통한 OAuth2 사용자 처리 MberVO mber = unifiedLoginService.processOAuth2User( userInfo.getEmail(), unifiedLoginService.convertProviderToMbrType(userInfo.getProvider()), userInfo.getId(), userInfo.getName(), request ); // 통합된 OAuth2 로그인 이력 저장 로직 사용 lgnHstryService.saveOAuth2LoginHistory(mber, request, userInfo.getProvider()); request.setAttribute("loginType", "OAUTH2"); // LoginUtil을 통한 통합 로그인 처리 loginUtil.successLogin(mber, request, response); String redirectUrl = String.format("%s/login.page?oauth_success=true&loginMode=%s&policyMode=%s", frontUrl, currentLoginMode, allowMultipleLogin ? "Y" : "N"); getRedirectStrategy().sendRedirect(request, response, redirectUrl); } catch (Exception e) { handleOAuth2Error(response, e); } } /** * OAuth2 사용자 정보 추출 - UnifiedLoginService의 통합 로직 사용 */ private UnifiedLoginServiceImpl.OAuth2UserInfo extractUserInfo(Authentication authentication) { try { // UnifiedLoginService의 통합된 사용자 정보 추출 메서드 사용 if (unifiedLoginService instanceof UnifiedLoginServiceImpl) { UnifiedLoginServiceImpl unifiedLoginServiceImpl = (UnifiedLoginServiceImpl) unifiedLoginService; return unifiedLoginServiceImpl.extractUserInfoFromAuthentication(authentication); } else { return null; } } catch (Exception e) { return null; } } /** * OAuth2 오류 처리 */ private void handleOAuth2Error(HttpServletResponse response, Exception e) throws IOException { String message = URLEncoder.encode("OAuth 로그인에 실패했습니다.", "UTF-8"); String errorUrl = String.format("%s/?error=oauth2_failed&message=%s", frontUrl, message); getRedirectStrategy().sendRedirect(null, response, errorUrl); } }