Spring Security
: 인증과 접근 제어를 위해 세부적인 맞춤 구성이 가능한 강력한 프레임워크
OAuth2 (Open Authorization 2)
: 사용자가 비밀번호를 제공하지 않고 타사 애플리케이션의 사용자 정보를 접근할 수 있도록 허용하는 표준 인증 프로토콜
1️⃣ Spring Security에서 OAuth2 Google 로그인하기
Spring Security는 SecurityFilterChain
을 @Bean
으로 등록하여 보안 설정을 적용합니다.
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
SecurityConfig.java
package com.koa.SpringOauth2Demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity // Spring Security 설정 활성화 어노테이션 (사용자가 직접 보안 설정 시 필요)
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth->auth.anyRequest().authenticated()) // anyRequest를 authenticated 설정
.oauth2Login(Customizer.withDefaults()); // OAuth2 로그인 사용
return http.build();
}
}
Google cloud에서 발급받은 client id, client secret 정보를 넣어주세요.
application.properties
spring.security.oauth2.client.registration.google.client-id={your-client-id}
spring.security.oauth2.client.registration.google.client-secret={your-client-secret}
실행하면 아래와 같이 구글 로그인이 가능하게 생성됩니다.

Spring Security를 사용하면 기본적으로 /login 경로에 로그인 페이지가 자동으로 생성됩니다.
2️⃣ OAuth2 로그인 후 정보 가져오기
Spring Security에서 OAuth2 사용자 OAuth2User 인터페이스를 구현한 클래스를 만듭니다.
이는 OAuth2 제공자한테 받은 정보(attributes), 권한(authorities), 이름(name)을 관리하는 역할을 합니다.
User.java
*Spring Security에서 기본적으로 제공하는 DefaultOAuth2User
클래스도 있습니다.
package com.koa.SpringOauth2Demo;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2User;
import java.util.Collection;
import java.util.Map;
public class User implements OAuth2User {
private final Collection<? extends GrantedAuthority> authorities; // 권한 목록
private final Map<String, Object> attributes; // 정보
private final String nameAttributeKey; // 식별 키
public User(Collection<? extends GrantedAuthority> authorities, Map<String, Object> attributes, String nameAttributeKey) {
this.authorities = authorities;
this.attributes = attributes;
this.nameAttributeKey = nameAttributeKey;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getName() {
return attributes.get(nameAttributeKey).toString();
}
}
Spring Security의 DefaultOAuth2UserService
를 상속받고, 이 중 사용자 정보를 가져오는 loadUser() 매서드를 구현합니다.
UserService.java
package com.koa.SpringOauth2Demo;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.Map;
@Service
public class UserService extends DefaultOAuth2UserService {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest){
OAuth2User oAuth2User = super.loadUser(userRequest); // 사용자 정보 가져옴
Map<String, Object> attributes = oAuth2User.getAttributes();
String userId = attributes.get("sub").toString();
String email = attributes.get("email").toString();
System.out.println("userId = " + userId);
System.out.println("email = " + email);
return new User(Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")), attributes, "email");
}
}
loadUser 함수에서 return을 추가로 설명하자면
new SimpleGrantedAuthority("ROLE_USER")으로 사용자 권한을 설정하고,
Collections.singleton()`으로 권한이 하나만 있는 불변의 set를 생성합니다.
SecurityConfig.java
package com.koa.SpringOauth2Demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final UserService userService;
public SecurityConfig(UserService userService) {
this.userService = userService;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth->auth.anyRequest().authenticated())
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(userService)) // OAuth2 로그인 후 사용자 정보 처리
.defaultSuccessUrl("/user/info") //성공 시 리다이렉트
);
return http.build();
}
}
로그인 성공 시 리다이렉트할 페이지를 생성해줍니다.
UserController.java
package com.koa.SpringOauth2Demo;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/info")
public Map<String, Object> getUserInfo(@AuthenticationPrincipal User user){
return user.getAttributes();
}
}

완성~~
다음에 이어서 OAuth2 로그인 후 JWT 토큰 발급과 OAuth2 로그아웃 처리도 작성해보겠습니다.
'Server > Java, Spring' 카테고리의 다른 글
SOLID: 좋은 객체 지향 설계의 5가지 원칙 (0) | 2025.01.04 |
---|