SpringBoot - OAuth2 로 카카오 로그인

2024. 5. 10. 16:37Full Stack Course 풀스택과정/SPRING

728x90

배울내용:

OAuth2 실행테스트

OAuth2 구글 로그인

스프링부트 OAuth2 

SpringBoot OAuth2

카카오 로그인 만들기

kakao 로그인 

카카오 로그인 연동

액세스 토큰 만들기

인증 관련 설정값

OAuth 뷰 구성

 

 

이번 포스팅을 Springboot로 카카오로 인증로그인 해볼것이다 

 

 

만약 추가적으로 구글 로그인이 하고싶으면 아래의 링크로 가자

 

https://sarimus.tistory.com/123

 

SpringBoot - OAuth2 로 구글 로그인 (1) (토큰 발급받기)

배울내용: SpringBoot - OAuth2 OAuth2 로 구글 로그인 스프링부트 토큰 발급받기 구글 클라우드 콘솔 OAuth 서비스 구현하기 구글 로그인 만들기 스프링 부트 구글로그인 연동 스프링 부트 구글 로그인

sarimus.tistory.com

 

 

 

 

 

 

 

 

먼저 카카오 developer 에서 설정하는것은 아래의 것처럼 가보자

필자도 아래의 블로그를 참고해서 했다 (아래블로그도 어느정도 되나 버전이 바뀌면서 안되는 케이스로 바뀜) 

 

https://velog.io/@zhyun/spring-boot-OAuth-2-kakao-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%97%B0%EB%8F%99

 

Spring Boot: OAuth2 kakao 로그인 연동

kakao 🍫

velog.io

 

[출저 - 2303100353-231116.log

 

 

 

2. Spring Boot 에서 설정

1. OAuth2 Client Dependency  추가

외부 서비스에서 OAuth 인증을 받아 사용하려는 것이기 때문에
새로운 프로젝트를 만들때 Spring Initializer에서 OAuth2 Client 를 추가해준다.

 

버전참고 

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.5'
    id 'io.spring.dependency-management' version '1.1.4'
}

 

또는 그냥 build.gradle 에 dependency 를 아래처럼 추가해주면 된다 

implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

 

2. appication.yml 설정 파일 작성

공식 문서
카카오 로그인 api 공식 문서

 

위에 블로그 포스팅에서는 아래처럼 나와 있다 

 

spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            client-id: ${kakao.client.id} # 앱키 -> REST API 키
            client-secret: ${kakao.client.secret} # 카카오 로그인 -> 보안 -> Client Secret 코드
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/kakao" # yml 파일에서 {} 가 spring 특수문자로 인식되게 하기 위해 " " 사용
            client-authentication-method: POST
        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 # 식별자 . 카카오의 경우 "id" 사용

그러나 아마 저대로 실행하면 서버에러 500 뜰것이다

 

 

그래서 아래처럼 써줘야한다 

spring: 
  security:
    oauth2:
      client:
        registration:
          kakao:
            client-id: 아까 카카오 dev 받은 내  REST API 키
            client-secret:   Client Secret 코드
            redirect-uri: "http://localhost:8080/login/oauth2/code/kakao"
            client-authentication-method: client_secret_post
            authorization-grant-type: authorization_code
            scope: account_email #동의 항목
            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

 

차이점이 있다면  provider 가 "-" 에서 "_" 으로 바뀌였고 client-authentication-method 가 POST 방식이 아닌 

authrozation_code  으로 바뀌었다 

 

 

 

 

 

그리고또한 기존에 config 코드에 6.1 버전이하로는 안된다고 deprecated 되었다고 되있으면서 csrf 나 disable  그리고 service 부분에서 빨간줄로 밑줄그여있을것이다 

 

 

이부분을 "람다식" 으로 바꿔주면 다해결된다 

 

 

1. 의존성 삽입 ( build.gradle)

아래처럼 딱 카카오 로그인에 필요한 것들만 만들었다

먼저 Oauth2 를 사용할 Dependency 와 그외에 dependency 를 build.gradle 에 아래처럼 넣어주자

 

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.5'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.codehows'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

 

 

2. 실행시켜줄 html 화면 만들기

먼저 실행시켜줄 화면을 만들어준다

template 패키지에 login.html 을 만들어주고 아래처럼 만들어준다

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="/oauth2/authorization/kakao">카카오 로그인</a>

</body>
</html>

 

 

 

3.  로그인 Controller 구현 

카카오 로그인 요청 시 인가 코드 받기, 토큰 받기, 사용자 로그인 처리의 과정을 수행할 Controller 코드를 작성한다.

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/login")
public class LoginController {
    @GetMapping
    public String login(){
        return "login";
    }
}

 

 

 

 

 

4.  사용자 인증을 처리 (Service 구현 )

 

이 코드는 Spring Security 및 OAuth2를 사용하여 사용자 인증을 처리하는 서비스 클래스를 정의

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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 java.util.List;

@Service
public class OAuth2UserService extends DefaultOAuth2UserService {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);

        // Role generate
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ADMIN");

        // nameAttributeKey
        String userNameAttributeName = userRequest.getClientRegistration()
                .getProviderDetails()
                .getUserInfoEndpoint()
                .getUserNameAttributeName();

        // DB 저장로직이 필요하면 추가

        return new DefaultOAuth2User(authorities, oAuth2User.getAttributes(), userNameAttributeName);
    }
}

 

 

 

5.  Spring Security를 사용하여 OAuth2 로그인을 구성 (Config 구현) 

이 코드는 Spring Security를 사용하여 OAuth2 로그인을 구성하고, 로그인 성공 시 원하는 동작을 수행하는 데 사용된다. 예를 들어, 사용자의 인증 정보를 기반으로 사용자 정보를 응답하거나, 세션을 설정하거나 다양한 작업을 수행할 수 있다.

 

아마 이부분에서 다들 오류가 뜨는데 람다식으로 

        .csrf((csrf) ->
                        csrf.disable()
                );

 

이런식으로 바꿔주면 작동할것이다 

import com.codehows.animalcafe.service.OAuth2UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {
    private final OAuth2UserService oAuth2UserService;

    public SecurityConfig(OAuth2UserService oAuth2UserService) {
        this.oAuth2UserService = oAuth2UserService;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf((csrf) ->
                        csrf.disable()
                );
        http.authorizeHttpRequests(config -> config.anyRequest().permitAll());
        http.oauth2Login(oauth2Configurer -> oauth2Configurer
                .loginPage("/login")
                .successHandler(successHandler())
                .userInfoEndpoint(userInfo -> userInfo
                        .userService(oAuth2UserService)));
        return http.build();
    }

    @Bean
    public AuthenticationSuccessHandler successHandler() {
        return ((request, response, authentication) -> {
            DefaultOAuth2User defaultOAuth2User = (DefaultOAuth2User) authentication.getPrincipal();

            String id = defaultOAuth2User.getAttributes().get("id").toString();
            String body = """
                    {"id":"%s"}
                    """.formatted(id);

            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());

            PrintWriter writer = response.getWriter();
            writer.println(body);
            writer.flush();
        });
    }
}

 

 

 

 

 

5.  로그인 시도해보기

먼저 아까 만들것들을 메인에서 실행한뒤에

controller 에서 만든 login 을 localhost:8080/+ login 을 해주면 아래처럼 보이게된다

 

 

 

 

 

 

 

이 카카오 로그인을 클릭하게 되면

 

 

 

 

 

 

카카오 로그인창이 뜨고 

만약 이런창이 안나오면 제대로 된게 아니다 

 

 

그리고 이렇게 2단계 인증을 하라고 하면 카카오톡에서 

 

 

이렇게 인증메세지를 보내준다 (필자는 영어공부한다고 언어를 영어로 바꿔서 이렇게 나오지만 한글로 되어있으면 한글로 나옴)

 

 

 

 

그리고 인증이 완료 되면 아래처럼 보이게된다

 

 

 

 

이렇게 되면 성공적으로 카카오 로그인 연동을 성공한 것이다 

 

그리고 만약 Id 뿐만아니라 다른 email 을 원하면

 

 

@Bean
public AuthenticationSuccessHandler successHandler() {
    return ((request, response, authentication) -> {
        DefaultOAuth2User defaultOAuth2User = (DefaultOAuth2User) authentication.getPrincipal();

        String id = defaultOAuth2User.getAttributes().get("id").toString();
        String body = """
                {"id":"%s"}
                """.formatted(id);

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());

        PrintWriter writer = response.getWriter();
        writer.println(body);
        writer.flush();
    });
}

 

이부분에서 추가해주면 더받을수 있을것이다. 

 

 

 

728x90