Single Sign-On(SSO)는 사용자가 한 번의 로그인으로 여러 관련 시스템나 애플리케이션에 접근할 수 있게 해주는 인증 메커니즘입니다. 예를 들어, 회사의 이메일, 인트라넷 프로젝트 관리 도구 등을 각각 따로 로그인하지 않고도 하나의 로그인으로 모두 접근할 수 있는 것이 SSO의 예입니다.
a. Spring Security와 OAuth2
Spring Security는 인증 및 권한 부여를 처리하는 강력한 프레임워크입니다. OAuth2는 SSO를 구현할 때 자주 사용되는 인증 프로토콜 중 하나입니다.
1. 의존성 추가
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
spring:
security:
oauth2:
client:
registration:
google:
client-id: your-client-id
client-secret: your-client-secret
scope: openid, profile, email
provider:
google:
authorization-uri: https://accounts.google.com/o/oauth2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
user-name-attribute: sub
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
b. SSO 제공자 사용하기
직접 SSO를 구현하는 대신 KeyCloak, Okta, Auth0와 같은 외부 SSO 제공자를 사용할 수도 있습니다. 이들 서비스는 SSO 기능을 쉽게 통합할 수 있는 다양한 기능과 설정을 제공합니다.
취업 준비 중인 신입 Java/Spring 백엔드 개발자라면 이론을 실습을 통해 체득하는 것이 매우 중요합니다. SSO(Single Sign-On)를 이해하고 실제로 구현해보는 것은 큰 도움이 될 것입니다. 다음은 실습을 통해 SSO를 학습할 수 있는 몇 가지 프로젝트 아이디어와 단계별 가이드를 제공합니다.
이 프로젝트는 Spring Boot 애플리케이션에 Google OAuth2를 사용한 SSO를 통합하는 간단한 실습입니다.
http://localhost:8080/login/oauth2/code/google을 추가합니다.의존성 추가: pom.xml에 Spring Security와 OAuth2 클라이언트 의존성을 추가합니다.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
application.yml 설정: src/main/resources/application.yml 파일에 Google OAuth2 설정을 추가합니다.
spring:
security:
oauth2:
client:
registration:
google:
client-id: YOUR_GOOGLE_CLIENT_ID
client-secret: YOUR_GOOGLE_CLIENT_SECRET
scope: openid, profile, email
provider:
google:
authorization-uri: https://accounts.google.com/o/oauth2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
user-name-attribute: sub
YOUR_GOOGLE_CLIENT_ID와 YOUR_GOOGLE_CLIENT_SECRET을 실제 값으로 대체합니다.
src/main/java/com/example/demo/SecurityConfig.java 파일을 생성하고 다음과 같이 작성합니다.
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.defaultSuccessURL("/home", true);
}
}
HomeController.java: src/main/java/com/example/demo/HomeController.java 파일을 생성합니다.
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index";
}
@GetMapping("/home")
public String home(@AuthenticationPrincipal OAuth2User principal, Model model) {
model.addAttribute("name", principal.getAttribute("name"));
return "home";
}
}
Thymeleaf 템플릿 작성:
src/main/resources/templates/index.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to the SSO Demo</h1>
<a href="/oauth2/authorization/google">Login with Google</a>
</body>
</html>
src/main/resources/templates/home.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>Home Page</h1>
<p>Welcome, <span th:text="${name}"></span>!</p>
<a href="/logout">Logout</a>
</body>
</html>
http://localhost:8080에 접속하여 "Login with Google" 버튼을 클릭합니다./home 페이지로 리디렉션되며, 사용자 이름이 표시됩니다.Keycloak은 오픈 소스 인증 및 권한 부여 서버로, SSO를 쉽게 구현할 수 있습니다. 이 프로젝트에서는 Keycloak을 사용하여 SSO를 설정하고 Spring Boot 애플리케이션과 통합해보겠습니다.
bin 디렉토리로 이동하여 Keycloak 서버를 실행합니다../kc.sh start-devhttp://localhost:8080에 접속합니다. 초기 관리자 계정을 설정합니다.demo-realm을 생성합니다.spring-appopenid-connectconfidentialhttp://localhost:8081/*새 Spring Boot 프로젝트 생성: 포트 변경을 위해 application.yml을 사용하여 기본 포트를 8081로 변경합니다.
server:
port: 8081
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: spring-app
client-secret: YOUR_KEYCLOAK_CLIENT_SECRET
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope: openid, profile, email
provider:
keycloak:
issuer-uri: http://localhost:8080/realms/demo-realm
YOUR_KEYCLOAK_CLIENT_SECRET을 Keycloak에서 확인한 값으로 대체합니다.
보안 설정 클래스 작성:
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.defaultSuccessURL("/home", true);
}
}
컨트롤러 및 뷰 작성: 이전 프로젝트와 유사하게 HomeController와 Thymeleaf 템플릿을 작성합니다.
http://localhost:8081에 접속하여 로그인합니다./home 페이지로 리디렉션되며, 사용자 정보가 표시됩니다.이 프로젝트에서는 두 개 이상의 Spring Boot 애플리케이션을 설정하여 하나의 인증 서버(Keycloak 또는 Google)를 통해 SSO를 구현해봅니다.
application.yml에 동일한 OAuth2 클라이언트 설정을 추가합니다.8082로 설정하고 동일한 client-id와 client-secret을 사용합니다.http://localhost:8081)에 로그인합니다.http://localhost:8082)에 접근하면, 추가 로그인 없이 접근이 허용됩니다.실습을 통해 SSO의 개념과 구현 방법을 직접 경험해보는 것은 매우 유익합니다. 위의 프로젝트들을 따라하면서 SSO의 작동 원리와 Spring Boot와의 통합 방법을 깊이 있게 이해할 수 있을 것입니다. 또한, 실제 프로젝트에서 SSO를 적용할 때 고려해야 할 보안 사항과 최적화 방법에 대해서도 자연스럽게 익힐 수 있습니다. 꾸준한 실습과 학습을 통해 SSO에 대한 자신감을 키우세요. 화이팅입니다!