1. 네이버는 OAuth2 Client에서 지원하지 않기 때문에 수동으로 설정해 주어야 한다.
application.yml 수정
들여쓰기를 맞춰주어야 한다.
# 네이버는 OAuth2.0 공식 지원대상이 아니라서 provider 설정이 필요하다.
# 요청주소도 다르고, 응답 데이터도 다르기 때문이다.
naver:
client-id: 머시기
client-secret: 머시기
scope:
- name
- email
- profile_image
client-name: Naver # 클라이언트 네임은 구글 페이스북도 대문자로 시작하더라.
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/naver
2. 네이버 개발자 센터 가서 애플리케이션 등록
3. yml 수정
ID와 시크릿을 yml에 넣어준다.
그리고 네이버는 OAuth2 Client에 원래 없는 공급자기 때문에 provider를 추가해주어야 한다.
이를 참조하여 작성할 수 있다. (카카오 api에서 한번 해봐서 이해가 쉬웠다.)
4. PrincipalOauth2UserService 수정
else is에 provider=naver 해서 네이버 로그인을 하고 콘솔을 보면 이런식으로 나온다.
보면 getAttributes가 구글, 페이스북과 다르다는 걸 알 수 있다.
이런식으로 getAttributes안에 필요한 회원 정보가 다 들어 있다.
하지만 네이버는 getAttributes안에 response라는 키 안에 Map이 하나 더 들어가 있다.
String provider = userRequest.getClientRegistration().getRegistrationId(); //google?
OAuth2UserInfo oAuth2UserInfo = null;
if(provider.equals("google")) {
System.out.println("구글 로그인 요청");
oAuth2UserInfo = new GoogleUserInfo(oauth2User.getAttributes());
}else if(provider.equals("facebook")) {
System.out.println("페이스북 로그인 요청");
oAuth2UserInfo = new FacebookUserInfo(oauth2User.getAttributes());
}else if(provider.equals("naver")){
System.out.println("네이버 로그인 요청");
oAuth2UserInfo = new NaverUserInfo((Map<String, Object>) oauth2User.getAttributes().get("response"));
}else {
System.out.println("현재 구글과 페이스북만 지원됩니다.");
}
그래서 NaverUserInfo를 만들 때 인자에 Map 형태로 .getAttributes().get("response")를 받아서 oAuth2UserInfo를 구현해줘야 한다.
NaverUserInfo.java
package com.pure.security.config.oauth.provider;
import java.util.Map;
public class NaverUserInfo implements OAuth2UserInfo {
private Map<String, Object> attributes;
public NaverUserInfo(Map<String, Object> response) {
this.attributes = response;
}
@Override
public String getProviderId() {
return (String)attributes.get("id");
}
@Override
public String getProvider() {
return "naver";
}
@Override
public String getEmail() {
return (String)attributes.get("email");
}
@Override
public String getName() {
return (String)attributes.get("name");
}
}
최종 모습
package com.pure.security.config.oauth;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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 com.pure.security.config.auth.PrincipalDetails;
import com.pure.security.config.oauth.provider.FacebookUserInfo;
import com.pure.security.config.oauth.provider.GoogleUserInfo;
import com.pure.security.config.oauth.provider.NaverUserInfo;
import com.pure.security.config.oauth.provider.OAuth2UserInfo;
import com.pure.security.model.User;
import com.pure.security.repository.UserRepository;
@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
@Autowired
private UserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
System.out.println("userRequset.getClientRegistration: "+ userRequest.getClientRegistration()); //registrationId로 어떤 OAuth로 로그인 했는지 알 수 있음.
System.out.println("userRequset.getAccessToken: "+ userRequest.getAccessToken().getTokenValue());
OAuth2User oauth2User = super.loadUser(userRequest);
System.out.println("getAttributes: "+oauth2User.getAttributes());
String provider = userRequest.getClientRegistration().getRegistrationId(); //google?
OAuth2UserInfo oAuth2UserInfo = null;
if(provider.equals("google")) {
System.out.println("구글 로그인 요청");
oAuth2UserInfo = new GoogleUserInfo(oauth2User.getAttributes());
}else if(provider.equals("facebook")) {
System.out.println("페이스북 로그인 요청");
oAuth2UserInfo = new FacebookUserInfo(oauth2User.getAttributes());
}else if(provider.equals("naver")){
System.out.println("네이버 로그인 요청");
oAuth2UserInfo = new NaverUserInfo((Map<String, Object>) oauth2User.getAttributes().get("response"));
}else {
System.out.println("현재 구글과 페이스북만 지원됩니다.");
}
String providerId = oAuth2UserInfo.getProviderId();
String username = provider+"_"+oAuth2UserInfo.getProviderId();
String password = new BCryptPasswordEncoder().encode("1234");
String email = oAuth2UserInfo.getEmail();
String role = "ROLE_USER";
//해당 username이 이미 있는지 확인
User userEntity = userRepository.findByUsername(username);
//구글로 처음 로그인 하면 자동으로 회원가입 시킴.
if(userEntity == null) {
System.out.println("최초 "+provider+" 로그인으로 회원가입을 진행했습니다.");
userEntity = User.builder()
.username(username)
.password(password)
.email(email)
.role(role)
.provider(provider)
.providerId(providerId)
.build();
userRepository.save(userEntity);
}else {
System.out.println("회원가입 이력이 있습니다. 자동 로그인을 진행했습니다.");
}
return new PrincipalDetails(userEntity, oauth2User.getAttributes()); //이 PrincipalDetails가 Authentication 객체 안에 들어가게 됨.
}
}
'취업 준비 > Spring security' 카테고리의 다른 글
11. 보안 문제와 RSA (0) | 2022.02.24 |
---|---|
10. TCP는 무엇인가? (0) | 2022.02.24 |
8. 페이스북 Oauth 로그인 (0) | 2022.02.22 |
7. PrincipalDetails 객체를 이용하여 2가지 로그인 방식 통합 (0) | 2022.02.17 |
6. OAuth2 구글 로그인 (0) | 2022.02.17 |