쉽게 로그인할 수 있는 소셜 로그인을 연동하고자 한다 !!! 여러개가 있지만, 나는 그중에서도 카카오 로그인을 도입해본당
OAuth2를 사용하여 데이터를 주고 받아 사용자 정보를 전달할 것이다. (스프링 부트는 OAuth2 라이브러리를 제공함!)
OAuth2
OAuth2는 문자열로 구성된 토큰(token)을 주고받는 방식으로 토큰을 발행하거나 검사하는 방식을 통해서 서비스 간 데이터를 교환한다.
OAuth2 카카오 로그인 과정
1. 인가 코드
애플리케이션을 설정했을 때 받은 'REST API'를 이용해서 인가 코드를 받는다.
인가 코드는 'Redirect URI'로 지정한 곳으로 전달된다.
2. Access Token
1에서 받은 인가 코드는 2에서의 Client Secret과 같이 이용되어 Access Token을 생성한다.
Access Token은 원하는 데이터에 접근할 수 있는 권한을 가지는 역할이다. (중요한 것이니까 뺏기면 위험하기 때문에 유효 기간은 짧게 설정해야함)
3. 정보 획득
2에서 얻은 Access Token을 이용해서 사용자 정보를 요청한다 (주로 이메일 정보)
카카오 로그인 설정하기
1. kakao developers 에서 애플리케이션 등록하기
내 애플리케이션 > 애플리케이션 추가하기 로 들어가서 작성한다.
2. 플랫폼 지정
그리고 플랫폼을 지정하는 부분에서 'Web'으로 지정하고, '사이트 도메인'은 현재는 로컬 ! (나중에 호스팅이용할 때는 변경하도록 한다.)
3. 카카오 로그인 활성화
왼쪽 메뉴의 '카카오 로그인'을 활성화 한다.
활성화한 후에 'Redirect URI'를 필수로 지정할 것! 가장 중요! (http://localhost:8080/login/oauth2/code/kakao)
4. 동의 항목 지정
'동의 항목'을 지정한다. 이 부분에서는 필요한 것만 지정할 것!
5. Client Secret
로그인을 활성화한 후에 '보안'에서 'Client Secret' 키를 생성한다. (보관해둘것!)
스프링 설정하기
[build.gradle]
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
[application.yml]
spring:
security:
oauth2:
client:
registration:
kakao:
client-id: # 발급 받은 Client ID (REST KEY)
client-secret: # 발급 받은 Client Secret
client-authentication-method: client_secret_post
authorization-grant-type: authorization_code
scope:
- profile_nickname
- account_email
redirect-uri: http://localhost:8080/login/oauth2/code/kakao
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
로그인 연동
http.oauth2Login()
로그인 연동 후 이메일 구하기
로그인을 연동해서 카카오 서비스 로그인까지 성공해도 게시물작성을 못하는데, 로그인된 후에 전달하는 정보가 UserDetails 타입이 아니기 때문이다 ! 그래서 UserDetailsService 인터페이스를 구현했던 것처럼 OAuth2UserService 인터페이스를 구현해야 한다.
package com.example.board.security;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
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.OAuth2User;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
@Log4j2
@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
log.info("userRequest..");
log.info(userRequest);
log.info("oauth2 user .................");
ClientRegistration clientRegistration = userRequest.getClientRegistration();
String clientName = clientRegistration.getClientName();
log.info("NAME: " + clientName);
OAuth2User oAuth2User = super.loadUser(userRequest);
Map<String, Object> paramMap = oAuth2User.getAttributes();
String email = null;
switch (clientName){
case "kakao":
email = getKakaoEmail(paramMap);
break;
}
log.info("=====================");
log.info(email);
log.info("=====================");
return oAuth2User;
}
private String getKakaoEmail(Map<String, Object> paramMap){
log.info("KAKAO ----------------------");
Object value = paramMap.get("kakao_account");
log.info(value);
LinkedHashMap accountMap = (LinkedHashMap) value;
String email = (String) accountMap.get("email");
log.info("email..." + email);
return email;
}
}
소셜 로그인 설정 및 이메일 분리하기를 해보았다! 갈 길은 멀다! 런런
추가 생각
근데 추가로 기본 회원으로 가입한 사람들과 같은 이메일이 가진 사람이 있다면 소셜 로그인만으로 로그인이 완료되게 하고, 해당 이메일이 가진 사람이 없다면 새로운 회원으로 간주하여 멤버 도메인 객체를 직접 생성해고, dto로 반환한다.
그래서 social 이라는 속성을 추가하여 boolean으로 구분짓는 방법을 도입할 것이다 !!
'Tech > Spring | Spring Boot' 카테고리의 다른 글
[Spring Security] 토큰 인증을 위한 시큐리티 필터 (0) | 2024.05.14 |
---|---|
[Spring Boot] JWT 이란? (API 서버/Token) (0) | 2024.05.04 |
[Spring Security] UserDetailsService/ UserDetails/ 인증(Authentication)/ 인가(Authorization) (0) | 2024.05.02 |
[Spring] 의존성 주립(DI) 이란 ? 쉽게 알려줄게! (0) | 2024.04.29 |
[Spring DB] 트랜잭션 AOP 주의 사항 - 프록시 내부 호출 (0) | 2024.04.13 |
댓글