사이먼's 코딩노트
[SpringBoot] 소셜 로그인(카카오톡) 본문
[소셜 로그인(카카오톡) 적용]
- 웹 페이지를 구현할 때 카카오톡, 네이버, 구글 등을 이용한 소셜 로그인이 필요할 때가 있을 것이다.
- 이번에는 위와 같은 소셜 로그인 중 카카오톡을 이용한 방법을 알아봅시다.
- 앞서 진행했던 SBB 프로그램이 아닌 임시로 만들어 둔 다른 프로젝트를 통해 구현할 예정이기 때문에 코드를 참고하고 싶으시다면 아래 깃허브 리포지터리 주소를 통해 참고 부탁드립니다.
- 깃허브 리포지터리 주소 : https://github.com/psm817/sb_blog_2405
[Kakao Developer 설정]
- 웹 브라우저를 통해 카카오 디벨로퍼에 접속하여 로그인을 해줘야한다.
- 카카오 디벨로퍼 주소 : https://developers.kakao.com/
- 로그인이 완료되었다면 메뉴 상단에 있는 '내 어플리케이션'을 클릭하여 아래와 같이 접속한다.
- '애플리케이션 추가하기' 를 클릭한 후 앱 아이콘, 앱 이름, 회사명, 카테고리를 입력한다.
- 테스트를 위한 작업이라면 회사명은 앱 이름과 동일하게 작성해도 무방하고 카테고리는 본인이 진행하는 프로젝트와 연관지어 선택하는 것이 좋다.
- 애플리케이션을 추가하고, 추가된 애플리케이션을 클릭하면 앱 설정을 하는 대시보드로 진입하게 된다.
- 좌측에 나열된 메뉴 중 제품 설정의 '카카오 로그인' 메뉴를 클릭하고 활성화 설정에서 상태를 ON으로 변경해준다.
- 활성화를 해줬으면 좌측 메뉴에서 '동의항목' 메뉴를 클릭하고 개인정보에서 닉네임과 프로필 사진의 상태를 '필수 동의' 상태로 변경해준다.
- 본인이 가지고있는 카카오톡 프로필 사진을 보이지 않게 하고 싶다면 프로필 사진에 대한 상태는 굳이 변경할 필요는 없다.
- 상태를 변경할 때, 동의 목적란에는 로그인 또는 회원가입이라는 텍스트를 작성하고 저장해야한다.
- 위 과정을 모두 마쳤다면 좌측 메뉴에서 앱 설정의 '앱 키' 메뉴를 클릭하면 애플리케이션의 키 값을 볼 수 있다.
- 총 4가지 종류의 키 값이 나열되어 있는데, 그 중 REST API 키가 우리가 사용할 '클라이언트 ID' 라고 생각하면 된다.
[application-secert.yml 수정]
- 현재 소셜 로그인을 적용할 프로그램의 구조는 기존의 application.yml만을 사용하지 않고, 개발용 application-dev.yml과 소셜 로그인과 같은 인증 키 유출을 막기 위한 application-secert.yml을 함께 사용하고 있다.
- 또한 소셜 로그인을 적용하기 위해서는 OAuth2라는 Open Authorization 2.0 인증 및 권한 부여를 위한 개방형 표준 프로토콜을 사용해야 한다.
- 그렇기 때문에 application-secert.yml에 아래의 코드를 적용하고, CLIENT_ID 부분에 초기 카카오 디벨로퍼에서 얻은 REST API 키 값을 넣어준다.
spring:
security:
oauth2:
client:
registration:
kakao:
clientId: CLIENT_ID
mail:
password: NEED_TO_INPUT
custom:
security:
oauth2:
client:
registration:
kakao:
devUser:
oauthId: oauthId
nickname: nickname
[라이브러리 추가]
- 위와 같이 세팅이 완료가 되면 build.gradle에서 OAuth2 라이브러를 아래와 같이 추가해준다.
- 코드를 붙혀넣었을 때 반드시 Load Gradle Changes를 통해 라이브러리 활성화를 해줘야한다.
// oauth
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
[SecurityConfig.java 수정]
- 현재 스프링 시큐리티에 대한 설정은 모두 SecurityConfig.java 클래스에서 담당하고 있다.
- 전에 로그인, 로그아웃을 구현하면서 formLogin과 logout의 매핑 주소가 모두 세팅되어 있다면 아래 코드와 같이 중간에 oauth2Login 로그인 속성을 추가한다.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
.formLogin(
formLogin -> formLogin
.loginPage("/member/login")
.defaultSuccessUrl("/")
)
.oauth2Login(
oauth2Login -> oauth2Login
.loginPage("/member/login")
)
.logout(
logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/member/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
)
;
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
[application.yml 수정]
- 다음은 oauth2를 적용하기 위해 application.yml에서 아래와 같이 코드 수정이 필요하다.
- 항상 주의할 점은 application.yml은 들여쓰기와 내어쓰기를 꼼꼼히 확인해야 한다. 그렇지 않으면 스프링부트 자체가 실행되지 않을 수도 있기 때문에 항상 조심해야 한다.
spring:
profiles:
active: dev
include: secret
security:
oauth2:
client:
registration:
kakao:
scope:
client-name: Kakao
authorization-grant-type: authorization_code
redirect-uri: 'http://localhost:8010/{action}/oauth2/code/{registrationId}'
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
datasource:
driver-class-name: org.mariadb.jdbc.Driver
jpa:
properties:
hibernate:
default_batch_fetch_size: 100
show_sql: true
format_sql: true
use_sql_comments: true
logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.orm.jdbc.bind: TRACE
org.hibernate.orm.jdbc.extract: TRACE
org.springframework.transaction.interceptor: TRACE
[Redirect URI 설정]
- 여기까지 완료됐다면 다시 카카오 디벨로퍼에 접속하여 '카카오 로그인' 메뉴를 선택한 후 하단의 'Redirect URI' 항목에 application.yml에서 작성한 redirect-uri 주소를 동일하게 입력해야 한다.
[MemberService.java 수정]
- 이제는 소셜 로그인 처리를 위한 몇 가지 수정이 필요하다.
- 소셜 로그인을 통해 가입 또는 로그인을 했을 경우, 비밀번호는 따로 필요없기 때문에 최초 회원 세팅을 해주는 메서드가 필요하다.
- 아래 코드는 MemberService.java 클래스에서 whenSocailLogin() 메서드를 추가한 모습이다.
@Transactional
public Member whenSocialLogin(String providerTypeCode, String username, String nickname) {
Optional<Member> opMember = findByUsername(username);
if (opMember.isPresent()) return opMember.get();
// 소셜 로그인를 통한 가입시 비번은 없다.
return signup(username, "", nickname, ""); // 최초 로그인 시 딱 한번 실행
}
[CustomOAuth2UserService.java 생성]
- 추가로 소셜(카카오톡) 로그인이 성공할 때 마다 위에서 생성한 whenSocialLogin() 메서드가 실행되어 문제없이 데이터베이스에 회원이 추가될 수 있게 기본 정보를 가공하고 데이터 필터 역할을 하는 서비스가 추가로 필요하다.
- 아래는 CustomOAuth2UserService.java 클래스를 새로 생성하여 추가한 코드이다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final MemberService memberService;
// 카카오톡 로그인이 성공할 때 마다 이 함수가 실행된다.
@Override
@Transactional
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
String oauthId = oAuth2User.getName();
Map<String, Object> attributes = oAuth2User.getAttributes();
Map attributesProperties = (Map) attributes.get("properties");
String nickname = (String) attributesProperties.get("nickname");
String providerTypeCode = userRequest.getClientRegistration().getRegistrationId().toUpperCase();
String username = providerTypeCode + "__%s".formatted(oauthId);
Member member = memberService.whenSocialLogin(providerTypeCode, username, nickname);
List<GrantedAuthority> authorityList = new ArrayList<>();
return new CustomOAuth2User(member.getUsername(), member.getPassword(), authorityList);
}
}
class CustomOAuth2User extends User implements OAuth2User {
public CustomOAuth2User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
@Override
public Map<String, Object> getAttributes() {
return null;
}
@Override
public String getName() {
return getUsername();
}
}
[웹 페이지 수정]
- 실제 웹 화면에 카카오와 연동되는 로그인 링크를 보여주기 위해 아래와 같이 웹 페이지 템플릿 수정이 필요하다.
- 아래 작성된 코드는 디자인 없이 기능만 구현되도록 작성되어 있기 때문에 참고만 바랍니다.
<div>
메인
<a sec:authorize="isAnonymous()" href="/member/login">로그인</a>
<div>
<a sec:authorize="isAnonymous()" href="/oauth2/authorization/kakao">카카오 로그인</a>
</div>
<a sec:authorize="isAuthenticated()" href="/member/logout">로그아웃</a>
<a href="/member/signup">회원가입</a>
</div>
- sec:authorize="isAnonymous()" 속성을 추가하여 로그아웃인 상태에서만 '카카오 로그인' 이라는 버튼 링크가 보이도록 하고 로그인이 완료되면 보이지 않도록 하였다.
- 실제로 프로그램을 재실행하면 '카카오 로그인' 이라는 버튼이 생긴 것을 확인할 수 있다.
- 생성된 '카카오 로그인' 버튼을 클릭하면 아래와 같이 애플리케이션에 대한 동의를 구하고 카카오 계정으로 로그인을 하는 화면이 나타난다.
반응형
'Java > SpringBoot' 카테고리의 다른 글
[SpringBoot] Cookie / Session / JWT (2) | 2024.06.15 |
---|---|
[SpringBoot] 이메일 발송 (0) | 2024.05.28 |
[SpringBoot] 검색 기능 구현 (0) | 2024.05.17 |
[SpringBoot] 앵커 이동 / 마크다운 적용 (0) | 2024.05.16 |
[SpringBoot] 앵커 이동 / 마크다운 적용 (0) | 2024.05.16 |