You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
이 예제는 SSO 서버에 로그인 요청을 보내고, 인증 후 사용자 정보를 받아와 Spring 애플리케이션에 로그인 세션을 만드는 과정을 보여줍니다.
importlombok.RequiredArgsConstructor;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.servlet.mvc.support.RedirectAttributes;
importjavax.servlet.http.HttpServletRequest;
@Controller@RequestMapping("/sso")
@RequiredArgsConstructor@Slf4jpublicclassSsoController {
privatefinalSsoServicessoService;
@Value("${sso.login.url}")
privateStringssoLoginUrl;
@GetMapping("/login")
publicStringssoLogin(HttpServletRequestrequest) {
// 1. 이미 SSO 인증이 되어 있는지 확인StringuserId = ssoService.getSsoUserId(request);
if (userId != null) {
// 2. SSO 인증이 이미 되어 있다면, 바로 로그인 처리 페이지로 리다이렉트return"redirect:/sso/callback?userId=" + userId;
} else {
// 3. SSO 인증이 되어 있지 않다면, SSO 로그인 페이지로 리다이렉트// returnUrl을 통해 로그인 후 돌아올 주소 지정StringreturnUrl = request.getRequestURL().toString();
return"redirect:" + ssoLoginUrl + "?returnUrl=" + returnUrl;
}
}
@GetMapping("/callback")
publicStringssoCallback(
HttpServletRequestrequest,
RedirectAttributesredirectAttributes) {
// 4. SSO로부터 받은 사용자 ID를 추출StringuserId = request.getParameter("userId");
if (userId == null) {
log.warn("SSO callback failed: userId is null");
redirectAttributes.addFlashAttribute("errorMsg", "SSO 로그인 실패");
return"redirect:/login"; // 실패 시, 일반 로그인 페이지로
}
// 5. 추출한 userId로 우리 서비스의 사용자 정보 조회Useruser = ssoService.getUserDetailsByUserId(userId);
if (user == null) {
log.warn("User not found in DB: {}", userId);
redirectAttributes.addFlashAttribute("errorMsg", "사용자 정보를 찾을 수 없습니다.");
return"redirect:/login"; // 사용자 정보가 없으면 오류 메시지
}
// 6. Spring Security 또는 직접 세션에 로그인 정보 저장// Spring Security를 사용한다면 Authentication 객체를 생성하여 SecurityContext에 설정// 예시: loginService.createSession(request.getSession(), user);// 7. 로그인 성공 후, 메인 페이지로 리다이렉트return"redirect:/dashboard";
}
@GetMapping("/logout")
publicStringssoLogout() {
// 8. SSO 로그아웃 URL로 리다이렉트// SSO 서버에서 로그아웃 처리를 완료하도록 함return"redirect:" + ssoService.getSsoLogoutUrl();
}
}
ssoService.getSsoUserId(request)를 통해 SSO 서버에 이미 인증 정보가 있는지 확인합니다.
인증 정보가 없으면, ssoLoginUrl로 리다이렉트하여 사용자가 SSO 서버에서 로그인하도록 유도합니다. 이때 returnUrl을 함께 전달하여 SSO 로그인 완료 후 다시 돌아올 주소를 알려줍니다.
/sso/callback:
SSO 서버에서 로그인 성공 후, 사용자를 다시 우리 애플리케이션으로 돌려보낼 때 호출되는 엔드포인트입니다.
URL 파라미터로 전달된 userId를 받아와 사용자 정보를 추출합니다.
ssoService.getUserDetailsByUserId(userId)를 호출하여 추출된 userId로 애플리케이션의 데이터베이스에서 사용자의 상세 정보를 조회합니다.
조회된 사용자 정보(User 객체)를 기반으로 Spring Security나 HTTP Session에 로그인 상태를 저장합니다.
/sso/logout :
애플리케이션에서 로그아웃을 요청할 때, SSO 서버의 로그아웃 URL로 리다이렉트하여 SSO 세션까지 함께 종료합니다.
핵심 역할 분리(서비스 계층)
위 코드에서 SsoService는 SSO 연동의 로직을 추상화하는 역할을 합니다.
@ServicepublicclassSsoService {
@Value("${sso.logout.url}")
privateStringssoLogoutUrl;
publicStringgetSsoUserId(HttpServletRequestrequest) {
// SSO 솔루션의 API를 호출하여 요청 헤더나 쿠키에서 사용자 ID를 추출하는 로직// 예: SSOUtil.getSSOLoginData(request);// 이 부분은 SSO 솔루션마다 다르게 구현됩니다.return"exampleUser123"; // 예시 반환값
}
publicUsergetUserDetailsByUserId(StringuserId) {
// userId를 기반으로 DB에서 사용자 정보를 조회하는 로직// 예: userRepository.findByUserId(userId);returnnewUser(userId, "홍길동"); // 예시 객체 생성
}
publicStringgetSsoLogoutUrl() {
returnssoLogoutUrl;
}
}
이처럼 SSO 연동은 컨트롤러에서 인증 흐름을 제어하고, 서비스 계층에서 실제 SSO API 호출 및 DB 연동 로직을 처리하여 역할을 분리하는 것이 중요합니다.
정리
세션(session)을 이용한 로그인 정보 보관
코드를 보면 사용자가 SSO 인증을 통해 userId를 받아오면, ssoService.getUserDetailsByUserId(userId)를 호출하여 우리 서비스의 데이터베이스에서 사용자 상세 정보를 조회합니다. 이 정보는 User 객체에 담기게 되고, 이 User 객체를 loginService.createSession(request.getSession(), user);와 같은 방식으로 서버의 세션에 저장합니다.
세션에 사용자 정보를 보관하는 이유는 다음과 같습니다.
상태 유지: HTTP는 상태를 유지하지 않는(stateless) 프로토콜입니다. 따라서 사용자가 웹사이트의 여러 페이지를 이동할 때마다 '로그인 상태'라는 정보를 유지하려면, 서버에 사용자 정보를 저장해둘 공간이 필요합니다. 세션은 이를 위한 가장 일반적인 방법입니다.
보안: 사용자 정보가 클라이언트(브라우저)에 노출되지 않고 서버에 안전하게 저장됩니다.
리다이렉트(Redirect)를 이용한 URL 연동
로그인 처리 과정에서는 리다이렉트가 중요한 역할을 합니다.
SSO 서버로 리다이렉트: 사용자가 처음 로그인할 때 return "redirect:" + ssoLoginUrl + "?returnUrl=" + returnUrl; 코드를 통해 SSO 서버의 로그인 페이지로 사용자를 보냅니다. 이는 SSO 서버가 인증 처리를 전담하게 하는 것입니다.
우리 서비스로 리다이렉트: SSO 로그인에 성공하면, SSO 서버는 returnUrl을 이용해 다시 우리 서비스의 특정 URL(예: /sso/callback)로 사용자를 돌려보냅니다.
최종 목적지로 리다이렉트: /sso/callback에서 로그인 세션 생성까지 완료되면, return "redirect:/dashboard"; 코드를 통해 사용자가 최종적으로 보게 될 대시보드 페이지로 이동시킵니다.
요약하자면, 세션은 사용자 로그인 상태를 서버에 보관하는 저장소이고, 리다이렉트는 로그인 과정에서 사용자를 여러 URL로 이동시키는 방법이라고 할 수 있습니다. 이 두 가지를 결합하여 안전하고 유연한 SSO 로그인 기능을 구현하게 됩니다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
SSO 연동 Spring/Java 코드 예시
코드 분석
/sso/login:/sso/callback:/sso/logout:핵심 역할 분리(서비스 계층)
SsoService는 SSO 연동의 로직을 추상화하는 역할을 합니다.정리
세션(session)을 이용한 로그인 정보 보관
코드를 보면 사용자가 SSO 인증을 통해 userId를 받아오면,
ssoService.getUserDetailsByUserId(userId)를 호출하여 우리 서비스의 데이터베이스에서 사용자 상세 정보를 조회합니다. 이 정보는 User 객체에 담기게 되고, 이 User 객체를 loginService.createSession(request.getSession(), user);와 같은 방식으로 서버의 세션에 저장합니다.세션에 사용자 정보를 보관하는 이유는 다음과 같습니다.
상태 유지: HTTP는 상태를 유지하지 않는(stateless) 프로토콜입니다. 따라서 사용자가 웹사이트의 여러 페이지를 이동할 때마다 '로그인 상태'라는 정보를 유지하려면, 서버에 사용자 정보를 저장해둘 공간이 필요합니다. 세션은 이를 위한 가장 일반적인 방법입니다.
보안: 사용자 정보가 클라이언트(브라우저)에 노출되지 않고 서버에 안전하게 저장됩니다.
리다이렉트(Redirect)를 이용한 URL 연동
로그인 처리 과정에서는 리다이렉트가 중요한 역할을 합니다.
SSO 서버로 리다이렉트: 사용자가 처음 로그인할 때
return "redirect:" + ssoLoginUrl + "?returnUrl=" + returnUrl;코드를 통해 SSO 서버의 로그인 페이지로 사용자를 보냅니다. 이는 SSO 서버가 인증 처리를 전담하게 하는 것입니다.우리 서비스로 리다이렉트: SSO 로그인에 성공하면, SSO 서버는 returnUrl을 이용해 다시 우리 서비스의 특정 URL(예: /sso/callback)로 사용자를 돌려보냅니다.
최종 목적지로 리다이렉트: /sso/callback에서 로그인 세션 생성까지 완료되면,
return "redirect:/dashboard";코드를 통해 사용자가 최종적으로 보게 될 대시보드 페이지로 이동시킵니다.요약하자면, 세션은 사용자 로그인 상태를 서버에 보관하는 저장소이고, 리다이렉트는 로그인 과정에서 사용자를 여러 URL로 이동시키는 방법이라고 할 수 있습니다. 이 두 가지를 결합하여 안전하고 유연한 SSO 로그인 기능을 구현하게 됩니다.
Beta Was this translation helpful? Give feedback.
All reactions