빙응의 공부 블로그

[Spring]OAuth2.0 - 구현하기 본문

Spring/개인공부_실습

[Spring]OAuth2.0 - 구현하기

빙응이 2024. 7. 30. 20:09

[Spring]OAuth2.0 간단한 동작 원리 및 모식도 (tistory.com)

 

[Spring]OAuth2.0 간단한 동작 원리 및 모식도

📝실습 목표OAuth를 이용해 신뢰할 수 있는 외부 사이트로부터 인증을 받고 전달 받은 유저 데이터를활용하여 세션을 만들고 인가를 진행해보자(해당 방식은 코드 방식으로 진행할 것이다)  

quddnd.tistory.com

[Spring]OAuth2.0 - 필수 변수와 네이버 요청하기 (tistory.com)

 

[Spring]OAuth2.0 - 필수 변수와 네이버 요청하기

📝 OAuth2 소셜 로그인을 위한 변수 설정application.properties#registrationspring.security.oauth2.client.registration.서비스명.client-name=서비스명spring.security.oauth2.client.registration.서비스명.client-id=서비스에서 발급

quddnd.tistory.com

 

📝 OAuth2UserSerivce

저번 포스팅에서 OAuth2UserSerivce를 구현해야 한다고 하였다.

유저 데이터를 받기 위한 OAuth2UserSerivce를 구현하자 


@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2User oAuth2User = super.loadUser(userRequest); //유저 정보를 가지고 옴
        System.out.println(oAuth2User.getAttributes()); // 간단한 확인

        String registrationId = userRequest.getClientRegistration().getRegistrationId(); //어떤 서비스에서 온 아이디인지 확인
        OAuth2Response oAuth2Response = null;
        if (registrationId.equals("naver")) {

            oAuth2Response = new NaverResponse(oAuth2User.getAttributes());
        }
        else if (registrationId.equals("google")) {

            oAuth2Response = new GoogleResponse(oAuth2User.getAttributes());
        }
        else {

            return null;
        }

        String role = "ROLE_USER"; //현재는 강제로 user처리 나중에 개발을 하면 바꾸면 됨

        return new CustomOAuth2User(oAuth2Response, role);
    }
}

 

해당 Service는 인증을 통해 외부 사이트로 받아온 것을 저장하는 역할인데 문제는 naver, google 등 모든

사이트는 서로의 양식이 다르다는 것이다. 이것을 판별해주는 dto를 따로 만들어줘야 한다.

 

Naver Json
{
		resultcode=00, message=success, response={id=123123123, name=}
}

 

Google Json
{
		resultcode=00, message=success, id=123123123, name=
}

 

 

📝DTO 정의하기 

일단 필요한 데이터에 대한 인터페이스를 만든다.

public interface OAuth2Response {

    //제공자 (Ex. naver, google, ...)
    String getProvider();
    //제공자에서 발급해주는 아이디(번호)
    String getProviderId();
    //이메일
    String getEmail();
    //사용자 실명 (설정한 이름)
    String getName();
}

 

Naver
public class NaverResponse implements OAuth2Response{

    private final Map<String, Object> attribute;

    public NaverResponse(Map<String, Object> attribute) {

        this.attribute = (Map<String, Object>) attribute.get("response");
    }

    @Override
    public String getProvider() {

        return "naver";
    }

    @Override
    public String getProviderId() {

        return attribute.get("id").toString();
    }

    @Override
    public String getEmail() {

        return attribute.get("email").toString();
    }

    @Override
    public String getName() {

        return attribute.get("name").toString();
    }
}

 

Google
public class GoogleReponse implements OAuth2Response{

    private final Map<String, Object> attribute;

    public GoogleReponse(Map<String, Object> attribute) {

        this.attribute = attribute;
    }

    @Override
    public String getProvider() {

        return "google";
    }

    @Override
    public String getProviderId() {

        return attribute.get("sub").toString();
    }

    @Override
    public String getEmail() {

        return attribute.get("email").toString();
    }

    @Override
    public String getName() {

        return attribute.get("name").toString();
    }
}

 

 

📝 SecurityConfig 만들기 

예비로 OAuth2UserService를 만들었다면 이제 SecurityConfig에 등록을 해줘여한다, 

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final CustomOAuth2UserService customOAuth2UserService;

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

        http //개발환경이기에 csrf off
            .csrf((csrf) -> csrf.disable());
        http
            .formLogin((login) -> login.disable());
        http //httpBasic 방식 인증 off
            .httpBasic((basic) -> basic.disable());
        http
            .oauth2Login((oauth2) -> oauth2
                .userInfoEndpoint((userInfoEndpointConfig) -> userInfoEndpointConfig
                    .userService(customOAuth2UserService)));
        http
            .authorizeHttpRequests((auth) -> auth
                .requestMatchers("/", "/oauth2/**", "/login/**").permitAll()
                .anyRequest().authenticated());

        return http.build();
    }
}

 

 

📝CustomOAuth2User 생성

이제 서비스를 통해서 CustomOAuth2User 반환에 문제가 없기 때문에 인증 객체 주입을 위한 

UserDetails를 만들어줘야 한다.

public class CustomOAuth2User implements OAuth2User {

    private final OAuth2Response oAuth2Response;
    private final String role;

    public CustomOAuth2User(OAuth2Response oAuth2Response, String role) {

        this.oAuth2Response = oAuth2Response;
        this.role = role;
    }

    @Override
    public Map<String, Object> getAttributes() {

        return null;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        Collection<GrantedAuthority> collection = new ArrayList<>();

        collection.add(new GrantedAuthority() {

            @Override
            public String getAuthority() {

                return role;
            }
        });

        return collection;
    }

    @Override
    public String getName() {

        return oAuth2Response.getName();
    }

    public String getUsername() {

        return oAuth2Response.getProvider()+" "+oAuth2Response.getProviderId();
    }
}

 

구글 로그인 잘된다!