본문 바로가기
공부/Spring

[Spring] 스프링 OAuth2 네이버 로그인 (OAuth2 스프링 4편)

by 웅대 2023. 4. 1.
728x90
반응형

https://growth-coder.tistory.com/141

 

[Spring] 스프링 OAuth2 페이스북 로그인 (OAuth2 스프링 3편)

이전 구글 로그인에 이어서 페이스북 로그인도 진행해보려 한다. https://growth-coder.tistory.com/136 [Spring][Spring] 스프링 Oauth2 구글 로그인과 jpa 사용하여 유저 정보 데이터베이스에 저장 및 권한 설 htt

growth-coder.tistory.com

이전 포스팅에서 진행한 구글 로그인, 페이스북 로그인에 이어서 네이버 로그인을 해보려고 한다.

 

네이버 개발자 센터에 접속한다.

https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

 

로그인을 하고 Application -> 애플리케이션 등록에 들어간다.

 

약관 동의 후 계정 정보를 등록한다.

애플리케이션의 이름을 정하고

네이버 로그인을 선택하고 제공받을 정보를 선택한다.

api 서비스 환경은 pc를 선택하고 서비스 URL과 콜백 URL을 적어준다.

 

콜백 URL은 나중에 application.properties에 사용될 예정이므로 기억해둔다.

이제 하단의 등록 버튼을 누른다.

 

이제 Application -> 내 애플리케이션에 등록된 모습을 확인할 수 있다.

 

이제 등록된 내 애플리케이션에 들어가서 멤버 관리 탭에 들어간다.

테스터 아이디에 oauth2 로그인을 진행할 계정을 등록해준다.

만약 애플리케이션을 제작을 완료한 상황이면 네이버 로그인 검수 상태 탭에 들어가서 검수 요청을 해야한다.

 

그런데 지금은 테스트 하는 중이므로 멤버 관리 탭에서 직접 oauth2 로그인을 허용할 네이버 아이디를 적어주는 것이다.

 

다시 등록된 내 애플리케이션에 들어가 클라이언트 아이디와 클라이언트 시크릿을 확인할 수 있고 이를 application.properties에 적어준다.

<application.properties>

spring.security.oauth2.client.registration.naver.client-id=[클라이언트 아이디]
spring.security.oauth2.client.registration.naver.client-secret=[클라이언트 시크릿]
spring.security.oauth2.client.registration.naver.scope=name, email, profile_image
spring.security.oauth2.client.registration.naver.client-name=Naver
spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.naver.redirect-url=http://localhost:8080/login/oauth2/code/naver
#redirect-url에는 콜백 url에 적어준 값과 같은 값 입력
spring.security.oauth2.provider.naver.authorization-uri=https://nid.naver.com/oauth2.0/authorize
spring.security.oauth2.provider.naver.token-uri=https://nid.naver.com/oauth2.0/token
spring.security.oauth2.provider.naver.user-info-uri=https://openai.naver.com/v1/nid/me
spring.security.oauth2.provider.naver.user-name-attribute=response

 

loginForm.html에 네이버 로그인을 추가한다.

 

<loginForm.html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="/oauth2/authorization/google">google login</a>
<a href="/oauth2/authorization/facebook">facebook login</a>
<a href="/oauth2/authorization/naver">naver login</a>

</body>
</html>

이전 포스팅에서 구글과 페이스북에서 Attributes가 서로 달라서 따로 구현체를 만들어주었다.

 

네이버도 마찬가지로 Attributes가 구글, 페이스북과 다르다.

 

<google attributes>

{
   sub=111111111111,
   name=홍길동,
   given_name=길동,
   family_name홍,
   picture=[이미지 url]
   email=email@gmail.com,
   email_verified=true,
   locale=ko
}

 

<facebook attributes>

{
   id=107956215586143,
   name=김철수,
   email=adgildong1@gmail.com
}

 

<Naver attributes>

{
   resultcode=00,
   message=success,
   response={
      id=[id],
      profile_image=[이미지 url]
      email=[네이버 이메일],
      name=홍길동
   }
}

네이버 attributes를 잘 보면 구글과 페이스북과는 다르게 우리가 진짜 필요한 정보가 response안에 담겨 있다.

 

이런 특징을 고려해서 OAuth2MemberInfo를 네이버에 대해서 구현하면 된다.

 

이전 포스팅에서 만들었던 GoogleMemberInfo, FacebookMemberInfo와 크게 다르지는 않다.

 

<NaverMemberInfo>

public class NaverMemberInfo implements OAuth2MemberInfo{
    public NaverMemberInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    private Map<String, Object> attributes;
    @Override
    public String getProviderId() {
        return (String) attributes.get("sub");
    }

    @Override
    public String getProvider() {
        return "naver";
    }

    @Override
    public String getName() {
        return (String) attributes.get("name");
    }

    @Override
    public String getEmail() {
        return (String) attributes.get("email");
    }
}

NaverMemberInfo를 생성할 때 attributes를 넣어주는데 이 때 주의해야한다.

<OAuth2MemberService>

@Service
@RequiredArgsConstructor
public class OAuth2MemberService extends DefaultOAuth2UserService {
    private final BCryptPasswordEncoder encoder;
    private final MemberRepository memberRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        OAuth2MemberInfo memberInfo = null;
        System.out.println(oAuth2User.getAttributes());
        System.out.println(userRequest.getClientRegistration().getRegistrationId());

        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        if (registrationId.equals("google")) {
            memberInfo = new GoogleMemberInfo(oAuth2User.getAttributes());
        } else if (registrationId.equals("facebook")) {
            memberInfo = new FacebookMemberInfo(oAuth2User.getAttributes());
        } else if (registrationId.equals("naver")) {
            memberInfo = new NaverMemberInfo((Map)oAuth2User.getAttributes().get("response"));
        } else {
            System.out.println("로그인 실패");
        }
        String provider = memberInfo.getProvider();
        String providerId = memberInfo.getProviderId();
        String username = provider + "_" + providerId; //중복이 발생하지 않도록 provider와 providerId를 조합
        String email = memberInfo.getEmail();
        String role = "ROLE_ADMIN"; //일반 유저
        System.out.println(oAuth2User.getAttributes());
        Optional<Member> findMember = memberRepository.findByName(username);
        Member member=null;
        if (findMember.isEmpty()) { //찾지 못했다면
            member = Member.builder()
                    .name(username)
                    .email(email)
                    .password(encoder.encode("password"))
                    .role(role)
                    .provider(provider)
                    .providerId(providerId).build();
            memberRepository.save(member);
        }
        else{
            member=findMember.get();
        }
        return new PrincipalDetails(member, oAuth2User.getAttributes());
    }
}

 

보다시피 네이버 로그인의 경우 getAttributes로 attributes를 가져와서 그 안의 response 값을 넣어줘야한다.

728x90
반응형

댓글