Spring Boot

스프링 부트로 OAuth2 구현 (페이스북,구글,네이버)

수수한개발자 2022. 6. 6.
728x90

모든 코드는 깃 저장소에 올려놨습니다

 

GitHub - jisu3316/Spring-Security: OAuth2

OAuth2 . Contribute to jisu3316/Spring-Security development by creating an account on GitHub....

github.com

 

OAuth란?

OAuth(Open Authoriztion)는 토큰 기반의 인증 및 권한을 위한 표준 프로토콜입니다. OAuth와 같은 인증 프로토콜을 통해 유저의 정보를 페이스북, 구글, 네이버 등의 서비스에서 제공받을 수 있고 이정보를 기반으로 어플리케이션 사용자에게 로그인이나 다른 여러 기능을 손쉽게 제공 할 수 있습니다. 자세한 내용은 생활코딩님의 유튜브영상을 참조 하시면 좋을것같습니다.

 

스프링부트로 OAu2를 통한 로그인 기능

스프링 부트로 OAuth2를 통한 로그인 기능을 제공할 수 있습니다. 여기서는 페이스북, 구글 ,네이버에서 제공하는 정보를 통해 사용자가 웹페이지에 손쉽게 로그인하는 기능을 구현할 것입니다. 스프링부트로 페이스북,구글 ,네이버 개발 페이지에 가서 인증설정을 해야합니다.

 

프로젝트 구조

\---src
+---main
|   +---java
|   |   \---com
|   |       \---example
|   |           \---security
|   |               |   SecurityApplication.java
|   |               |
|   |               +---config
|   |               |   |--SecurityConfig.java
|   |               |   |--WebMvcConfig.java
|   |               |   +---auth
|   |               |   |     PricipalDetails.java
|   |               |   |     PricipalDetailsService.java
|   |               |   +---oauth
|   |               |        | PrincipalOauth2UserService.java
|   |               |        +---provider
|   |               |             FaceBookUserInfo.java
|   |               |             GoogleUserInfo.java
|   |               |             NaverUserInfo.java         
|   |               +---controller
|   |               |       IndexController.java
|   |               |
|   |               |---model
|   |               |     User.java
|   |               |
|   |               \---repository
|   |                       UserRepository.java
|   |
|   \---resources
|       |   application.yml
|       |
|       +---static
|       \---templates
|               Index.html
|               joinForm.html
|               loginForm.html

의존성

plugins {
	id 'org.springframework.boot' version '2.6.8'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-mustache'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'

	//	 https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
	implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.6.0'

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

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

 

 

application.yml

server:
  port: 8080
  servlet:
    context-path: /
    encoding:
      charset: UTF-8
      enabled: true
      force: true

spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:3306/security?useUnicode=true&characterEncoding=utf-8
    username: cos
    password: cos1234

  jpa:
    hibernate:
      ddl-auto: update #create update none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
    properties:
      hibernate:
        format_sql: true
  security:
    oauth2:
      client:
        registration:
          naver:
            client-id: 발급받은 키 값
            client-secret: 발급받은 키 값
            redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}" # (== http://localhost:8080/login/oauth2/code/naver)
            authorization-grant-type: authorization_code
            scope: name, email, profile_image
            client-name: Naver
          google:
            client-id: 발급받은 키 값
            client-secret: 발급받은 키 값
            scope:
              - email
              - profile
          facebook:
            client-id: 발급받은 키 값
            client-secret: 발급받은 키 값
            scope:
              - email
              - public_profile
        provider:
          naver:
            authorization_uri: https://nid.naver.com/oauth2.0/authorize
            token_uri: https://nid.naver.com/oauth2.0/token
            user-info-uri: https://openapi.naver.com/v1/nid/me
            user_name_attribute: response


logging:
  level:
    org.hibernate.SQL: debug
    org.hibernate.type: trace

소스코드

SecurityApplication ( main 진입점 )

package com.example.security;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SecurityApplication {

	public static void main(String[] args) {
		SpringApplication.run(SecurityApplication.class, args);
	}

}

IndexController

package com.example.security.controller;

import com.example.security.config.auth.PrincipalDetails;
import com.example.security.model.User;
import com.example.security.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequiredArgsConstructor
public class IndexController {

    private final UserRepository userRepository;

    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @GetMapping("/test/login")
    public @ResponseBody String loginTest(Authentication authentication, @AuthenticationPrincipal PrincipalDetails userDetails) {  //DI(의존성 주입)
        System.out.println("/test/login ===================");
        PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
        System.out.println("authentication = " + principalDetails.getUser());
        System.out.println("userDetails = " + userDetails.getUser());
        return "세션 정보 확인하기";
    }

    @GetMapping("/test/oauth/login")
    public @ResponseBody String testOAuthlogin(Authentication authentication, @AuthenticationPrincipal OAuth2User oauth) {  //DI(의존성 주입)
        System.out.println("/test/oauth/login ===================");
        OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
        System.out.println("oAuth2User.getAttributes() = " + oAuth2User.getAttributes());
        System.out.println("oauth.getAttributes(): "+oauth.getAttributes());

        return "OAuth 세션 정보 확인하기";
    }

    @ResponseBody
    @GetMapping({"", "/"})
    public String index() {
        //머스테치 기본폴더 src/main/resources/
        //뷰리졸버 설정 : templates(prefix), .mustache( suffix) 생략가능!!
        //src/main/resources/templates/index.mustache
        return "hello";
    }

    //OAuth 로그인을 해도 PrincipalDetails 받을 수 있음
    //일반 로그인을 해도 PrincipalDetails 받을 수 있음
    @ResponseBody
    @GetMapping("/user")
    public String user(@AuthenticationPrincipal PrincipalDetails principalDetails) {
        System.out.println("principalDetails = " + principalDetails.getUser());
        return "user";
    }

    @ResponseBody
    @GetMapping("/admin")
    public String admin() {
        return "admin";
    }

    @ResponseBody
    @GetMapping("/manager")
    public String manager() {
        return "manager";
    }

    //스프링 시큐리티 해당주소를 낚아채간다. -SecurityConfig 파일 생성 후 작동안함.
    @GetMapping("/loginForm")
    public String loginForm() {
        return "loginForm";
    }

    @GetMapping("/joinForm")
    public String joinForm() {
        return "joinForm";
    }


    @PostMapping("/join")
    public String join(User user) {
        System.out.println(user);
        user.setRole("ROLE_USER");
        String rawPassword = user.getPassword();
        String encPassword = bCryptPasswordEncoder.encode(rawPassword);
        user.setPassword(encPassword);
        userRepository.save(user); //회원가입 잘됨. 이렇게하면 비밀번호가 1234로 들어감 => 시큐리티로 로그인을 할 수없음. 패스워드가 암호화가 안되었기 때문에.
        return "redirect:/loginForm";
    }

    @Secured("ROLE_ADMIN")
    @GetMapping("/info")
    public @ResponseBody String info() {
        return "개인정보";
    }

    @PreAuthorize("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")//함수가 시작전에.
    @GetMapping("/data")
    public @ResponseBody String data() {
        return "데이터정보";
    }
}

SecurityConfig

package com.example.security.config;

import com.example.security.config.oauth.PrincipalOauth2UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

// 구글 로그인이 완료된 뒤의 후처리가 필요함.
// 1. 코드받기(인증을받음,구글에 로그인이 됨), 2.엑세스토큰을받음(사용자정보에 접근 권한가능), 3.사용자 프로필 정보를 가져오고, 4-1. 그 정보를 토대로 회원가입을 자동으로 진행시키도록 함
// 4-2(이메일,전화번호,이름,아이디) 쇼핑몰 -> (집주소),백화점몰 ->(vip등급,일반등급)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)  //secured 어노테이션 활성화, preAuthorize,postAuthorize 어노테이션 활성화
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final PrincipalOauth2UserService principalOauth2UserService;

    public SecurityConfig(PrincipalOauth2UserService principalOauth2UserService) {
        this.principalOauth2UserService = principalOauth2UserService;
    }


    //해당 메서드의 리턴되는 오브젝트를 IoC로 등록해준다.
    @Bean
    public BCryptPasswordEncoder encodePwd() {
        return new BCryptPasswordEncoder();
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/user/**").authenticated() // /user/** 밑으로 들어오는 url는 인증이 필요하다.
                .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')") //hasRole 권한이 있어야한다.
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll()          //나머지 주소는 권한이 허용이된다.
                .and()
                .formLogin()
                .loginPage("/loginForm")
                //.usernameParameter("username2")  form에서 name값을 바꿔주려면 parameter 바꿔줘야함
                .loginProcessingUrl("/login")       //login 조수가 호출이되면 시큐리가 낚아채서 대신 로그인을 진행해줍니다.
                .defaultSuccessUrl("/")
                .and()
                .oauth2Login()
                .loginPage("/loginForm")  // 구글 로그인이 완료된 뒤의 후처리가 필요함. Tip.코드X, (엑세스토큰+ 사용자 프로필정보O)
                .userInfoEndpoint()
                .userService(principalOauth2UserService);

    }
}

 

  • http.csrf().disable : csrf보호기능을 disable > csrf에 대한 것은 글을 한번 다뤄보겠습니다..
  • authorizeRequests() : 시큐리티 처리에 HttpServlectRequest를 이용하겠다.
  • antMatchers() : 특정한 경로를 지정합니다.
  • access(String) : 주어진 SpEl 표현식의 평가 결과가 true이면 접근을 허용하겠다.
  • hasRole(String) : 사용자가 주어진 역할이 있다면 접근을 허용하겠다.
  • anyRequest() : 그 외 경로들을 뜻합니다.
  • permitAll() : 무조건 접근을 허용
  • loginPage("/loginForm") : 인증이 필요할 때 이동하는 페이지 설정하는 api입니다. 해당 api설정을 하지 않을 경우 spring security가 제공하는 템플릿으로 연결됩니다.
  • defaultSuccessUrl("/") : 인증이 성공하였을때 default로 이동하는 URL을 지정하는 api 입니다.
  • usernameParameter("username") : spring security 에서 기본값인 username,password 파라미터의 값을 변경하게 해주는 api입니다. 
  •  loginProcessingUrl("/login") : 폼테그의 action url을 설정하는 api입니다. default 값은 default login 입니다.

여기까지 하면 기본적인 로그인을 할 때의 기능들입니다. 그리고 저는 oauth2Login을 사용할것이기 때문에 추가를 해줍니다.

 

 

 

 

 

securty를 적용하려면 spring boot 2.7.0 버전 미만은 WebSecurtiyConfigurerAdapter를 상속받아 configure 메소드를 구현 해줘야 합니다. 

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)  //secured 어노테이션 활성화, preAuthorize,postAuthorize 어노테이션 활성화
public class SecurityConfig {

    private final PrincipalOauth2UserService principalOauth2UserService;

    public SecurityConfig(PrincipalOauth2UserService principalOauth2UserService) {
        this.principalOauth2UserService = principalOauth2UserService;
    }


    //해당 메서드의 리턴되는 오브젝트를 IoC로 등록해준다.
    @Bean
    public BCryptPasswordEncoder encodePwd() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/user/**").authenticated() // /user/** 밑으로 들어오는 url는 인증이 필요하다.
                .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')") //hasRole 권한이 있어야한다.
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll()          //나머지 주소는 권한이 허용이된다.
                .and()
                .formLogin()
                .loginPage("/loginForm")
                //.usernameParameter("username2")  form에서 name값을 바꿔주려면 parameter 바꿔줘야함
                .loginProcessingUrl("/login")       //login 조수가 호출이되면 시큐리가 낚아채서 대신 로그인을 진행해줍니다.
                .defaultSuccessUrl("/")
                .and()
                .oauth2Login()
                .loginPage("/loginForm")  // 구글 로그인이 완료된 뒤의 후처리가 필요함. Tip.코드X, (엑세스토큰+ 사용자 프로필정보O)
                .userInfoEndpoint()
                .userService(principalOauth2UserService);

        return http.build();
    }

spring boot 2.7.0 버전 이상부터는 위와 같이 configure 대신 SecurityFilterChain을 빈으로 등록해줘서 사용해줘야합니다.

ref: https://www.codejava.net/frameworks/spring-boot/fix-websecurityconfigureradapter-deprecated

 

PrincipalDetails.java

package com.example.security.config.auth;

// 시큐리티가 /login 주소 요청이 오면 낚아채서 로그인을 진행시킨다.
// 로그인을 진행이 완료가 되면 시큐리티 session을 만들어 줍니다. (Security ContextHolder)
// 시큐리티에 들어갈수있는 정보가 정해져있다.  오브젝트 => Authentication 타입 객체
// Authentication 안에 User 정보가 있어야 됨.
// User오브젝트 타입 => UserDetails 타입 객체

//Security Session 영역이 있음. => Authentication => UserDetails(PrincipalDetails) 타입이여야함.
//Security Session을 꺼내면 Authentication 객체가 나옴. UserDetails을 꺼내면 User정보에 접근가능함.

import com.example.security.model.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

@Data
public class PrincipalDetails implements UserDetails, OAuth2User {

    private User user;
    private Map<String,Object> attributes;


    //일반 로그인
    public PrincipalDetails(User user) {
        this.user = user;
    }
    //OAuth 로그인
    public PrincipalDetails(User user, Map<String, Object> attributes) {
        this.user = user;
        this.attributes = attributes;
    }


    //해당 유저의 권한을 리턴하는 곳!!
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collect = new ArrayList<>();
        collect.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getRole();
            }
        });
        return collect;
    }

    //패스워드 리턴
    @Override
    public String getPassword() {
        return user.getPassword();
    }

    //유저이름 리턴턴
    @Override
    public String getUsername() {
        return user.getUsername();
    }

    //계정 만료되었는지 true ==만료되지 않았다.
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    //계정 잠겼니  true ==안잠겼다
   @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    //계정의 비밀번호 1년이 지났니 true = 아니요
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    //계정이 활성화 되었니 true = 아니요
    @Override
    public boolean isEnabled() {

        //우리 사이트에서 1년동안 회원이 로그인을 안하면!! 휴면계정으로 하기로 함.
        //현재시간 - 로그인 시간 => 1년을 초가화면 return false; 하면됨.
        return true;
    }

    //OAuth2User 구현 메소드
    @Override
    public Map<String, Object> getAttributes() {
        return attributes;
    }

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

PrincipalDeltailsService.java

package com.example.security.config.auth;

import com.example.security.model.User;
import com.example.security.repository.UserRepository;
import lombok.RequiredArgsConstructor;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

// 시큐리티 설정에서 loginProcessingUrl("/login");
// /login 요청이 오면 자동으로 UserDetailsService 타입으로 Ioc되어 있는 loadUserByUsername 함수가 실행
@Service
@RequiredArgsConstructor
public class PrincipalDetailsService implements UserDetailsService {

    private final UserRepository userRepository;
    // 시큐리티 session(내부 Authentication(내부 UserDetails)) = Authentication(내부 UserDetails) = UserDetails
    //함수 종료시 @AuthenticationPrincipal 어노테이션 만들어진다.
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username: "+username);
        User userEntity = userRepository.findByUsername(username);
        if (userEntity != null) {
            return new PrincipalDetails(userEntity);
        }
        return null;
    }
}

그리고 oauth2 구글,네이버,페이스북 등으로 로그인하기를 눌렀을때 바로 회원가입이 되서 서비스를 이용하는데 지장이 없도록 구현하였습니다.

 

PrincipalOauth2UseService.java

package com.example.security.config.oauth;

import com.example.security.config.auth.PrincipalDetails;
import com.example.security.config.oauth.provider.FacebookUserInfo;
import com.example.security.config.oauth.provider.GoogleUserInfo;
import com.example.security.config.oauth.provider.NaverUserInfo;
import com.example.security.config.oauth.provider.OAuth2UserInfo;
import com.example.security.model.User;
import com.example.security.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
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 java.util.Map;

@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {



    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    private final UserRepository userRepository;

    public PrincipalOauth2UserService(@Lazy BCryptPasswordEncoder bCryptPasswordEncoder, @Lazy UserRepository userRepository) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.userRepository = userRepository;
    }

    //구글로 부터 받은 userRequest 데이터에 대한 후처리되는 함수
    //함수 종료시 @AuthenticationPrincipal 어노테이션 만들어진다.
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2User oAuth2User = super.loadUser(userRequest);
        // 구글로그인 버튼 클릭 -> 구글 로그인창 -> 로그인을 완료 -> code를 리넡(OAuth-Client라이브러리) -> AccecssToken요청
        // userRequest정보 -> loadUser함수 호출() -> 구글로 부터 회원 프로필을 받을 수 있음
        System.out.println("super.loadUser(userRequest).getAttribute(): "+oAuth2User.getAttributes());

        //회원가입을 강제로 진행
        OAuth2UserInfo oAuth2UserInfo = null;
        if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
            System.out.println("구글로그인 요청");
            oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
        }  else if (userRequest.getClientRegistration().getRegistrationId().equals("facebook")) {
            System.out.println("페이스북 로그인 요청");
            oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
        } else if (userRequest.getClientRegistration().getRegistrationId().equals("naver")) {
            System.out.println("네이버 로그인 요청");
            oAuth2UserInfo = new NaverUserInfo((Map)oAuth2User.getAttributes().get("response"));
        }else {
            System.out.println("우리는 구글과 페이스북,네이버만 지원해요.");
        }

        String provider = oAuth2UserInfo.getProvider();
        String providerId = oAuth2UserInfo.getProviderId();
        String username = provider+"_"+providerId; //username = google_107438726388440656699
        String password = bCryptPasswordEncoder.encode("지수");
        String email = oAuth2UserInfo.getEmail();
        String role = "ROLE_USER";

        User userEntity = userRepository.findByUsername(username);

        if (userEntity == null) {
            System.out.println("OAuth 로그인이 최초입니다.");
            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());

    }
}

OAuth2UserInfo.java

package com.example.security.config.oauth.provider;

public interface OAuth2UserInfo {
    String getProviderId();
    String getProvider();
    String getEmail();
    String getName();
}

인터페이스를 만들어 상속받게 만들었습니다.

 

FaceboockUserInfo

package com.example.security.config.oauth.provider;

import java.util.Map;

public class FacebookUserInfo implements OAuth2UserInfo {

    private Map<String, Object> attributes; //oauth2User.getAttributes()

    public FacebookUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }
    @Override
    public String getProviderId() {
        return (String) attributes.get("id");
    }

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

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

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

GoogleUserInfo

 

package com.example.security.config.oauth.provider;

import java.util.Map;

public class GoogleUserInfo implements OAuth2UserInfo {

    private Map<String, Object> attributes; //oauth2User.getAttributes()

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

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

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

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

 

package com.example.security.config.oauth.provider;

import java.util.Map;

public class NaverUserInfo implements OAuth2UserInfo {

    private Map<String, Object> attributes; //oauth2User.getAttributes()

    public NaverUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }
    @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");
    }
}
728x90

댓글