diff --git a/spring/build.gradle b/spring/build.gradle index 098b868..89b1051 100644 --- a/spring/build.gradle +++ b/spring/build.gradle @@ -53,6 +53,9 @@ dependencies { // Thymeleaf implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + + // Spring Security OAuth2 클라이언트 의존성 추가 + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' } sourceSets { diff --git a/spring/src/main/java/umc/spring/config/SecurityConfig.java b/spring/src/main/java/umc/spring/config/SecurityConfig.java index ccd9c4b..dd1b898 100644 --- a/spring/src/main/java/umc/spring/config/SecurityConfig.java +++ b/spring/src/main/java/umc/spring/config/SecurityConfig.java @@ -29,6 +29,11 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .logoutUrl("/logout") .logoutSuccessUrl("/login?logout") .permitAll() + ) + .oauth2Login(oauth2 -> oauth2 + .loginPage("/login") + .defaultSuccessUrl("/home", true) + .permitAll() ); return http.build(); diff --git a/spring/src/main/java/umc/spring/config/security/CustomOAuth2UserService.java b/spring/src/main/java/umc/spring/config/security/CustomOAuth2UserService.java new file mode 100644 index 0000000..d5a1da1 --- /dev/null +++ b/spring/src/main/java/umc/spring/config/security/CustomOAuth2UserService.java @@ -0,0 +1,64 @@ +package umc.spring.config.security; + +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import umc.spring.domain.Member; +import umc.spring.domain.enums.Gender; +import umc.spring.domain.enums.Role; +import umc.spring.repository.MemberRepository; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class CustomOAuth2UserService extends DefaultOAuth2UserService { + + private final MemberRepository memberRepository; + private final PasswordEncoder passwordEncoder; + + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + OAuth2User oAuth2User = super.loadUser(userRequest); + + Map attributes = oAuth2User.getAttributes(); + Map properties = (Map) attributes.get("properties"); + + String nickname = (String) properties.get("nickname"); + String email = nickname + "@kakao.com"; // 임시 이메일 생성 + + // 사용자 정보 저장 또는 업데이트 + Member member = saveOrUpdateUser(email, nickname); + + // 이메일을 Principal로 사용하기 위해 attributes 수정 + Map modifiedAttributes = new HashMap<>(attributes); + modifiedAttributes.put("email", email); + + return new DefaultOAuth2User( + oAuth2User.getAuthorities(), + modifiedAttributes, + "email" // email Principal로 설정 + ); + } + + private Member saveOrUpdateUser(String email, String nickname) { + Member member = memberRepository.findByEmail(email) + .orElse(Member.builder() + .email(email) + .name(nickname) + .password(passwordEncoder.encode("OAUTH_USER_" + UUID.randomUUID())) + .gender(Gender.MALE) // 기본값 설정 + .address("소셜로그인") // 기본값 설정 + .role(Role.USER) + .build()); + + return memberRepository.save(member); + } +} diff --git a/spring/src/main/resources/application.yml b/spring/src/main/resources/application.yml index 8b941ce..66b7fdf 100644 --- a/spring/src/main/resources/application.yml +++ b/spring/src/main/resources/application.yml @@ -19,4 +19,22 @@ spring: default_batch_fetch_size: 1000 mvc: problem-details: - enabled=false: \ No newline at end of file + enabled=false: + security: + oauth2: + client: + registration: + kakao: + client-authentication-method: client_secret_post + client-id: ${CLIENT_ID} + client-secret: ${CLIENT_SECRET} + redirect-uri: ${REDIRECT_URI} + authorization-grant-type: authorization_code + scope: profile_nickname + client-name: Kakao + provider: + kakao: + authorization-uri: https://kauth.kakao.com/oauth/authorize + token-uri: https://kauth.kakao.com/oauth/token + user-info-uri: https://kapi.kakao.com/v2/user/me + user-name-attribute: id \ No newline at end of file