JAVA/Spring Boot

(스프링 부트) 구글 로그인 구현

ri5 2021. 7. 13. 23:22

1. Security 설정

스프링 시큐리티를 사용하는데 쓸 기능들을 명시해준다

@RequiredArgsConstructor
// 스프링 시큐리티 설정 활성화
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final CustomOAuth2UserService customOAuth2UserService;

    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .headers().frameOptions().disable().disable()
                .authorizeRequests() //URL 별 권한 관리 옵션
                .antMatchers("/","/css/**","/images/**","/js/**","/api/**").permitAll() // 모든 사용자
                .antMatchers("/api2/**").hasRole(Role.USER.name()) // 유저 들만
                .anyRequest().authenticated() //설정값 이외의 URL
        .and()
                .logout()
                    .logoutSuccessUrl("/") //로그아웃 성공시 홈으로 이동
                    .invalidateHttpSession(true)
        .and()
                .oauth2Login() // OAuth 2 로그인 기능 설정
                    .userInfoEndpoint()// 로그인 성공이후 사용자 정보를 가져올때의 설정
                        .userService(customOAuth2UserService);// 로그인 성공시 후속 조치할 userService 구현체 등록

    }
}

 

커스텀한 서비스를 등록함

2. Service 구현

@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    private final UserRepository userRepository;
    private final HttpSession httpSession;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        String registrationId = userRequest.getClientRegistration().getRegistrationId();//네이버 로그인인지 구글로그인인지 서비스를 구분해주는 코드
        String userNAmeAttributeName = userRequest.getClientRegistration().getProviderDetails()
                .getUserInfoEndpoint().getUserNameAttributeName(); //OAuth2 로그인 진행시 키가 되는 필드값 프라이머리키와 같은 값 네이버 카카오 지원 x
        OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNAmeAttributeName, oAuth2User.getAttributes()); //OAuth2UserService를 통해 가져온 데이터를 담을 클래스

        User user = saveOrUpdate(attributes);

        httpSession.setAttribute("user", new SessionUser(user));

        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority(user.getRoleKey())),
                attributes.getAttributes(),
                attributes.getNameAttributeKey());
    }

    private User saveOrUpdate(OAuthAttributes attributes) {
        User user = userRepository.findByEmail(attributes.getEmail())
                .map(entity -> entity.update(attributes.getName(), attributes.getPicture()))
                .orElse(attributes.toEntity());

        return userRepository.save(user);
    }
}

 

loadUser()

3. Attribute 정의

@Getter
public class OAuthAttributes {
    private Map<String,Object> attributes;
    private String nameAttributeKey;
    private String name;
    private String email;
    private String picture;

    @Builder
    public OAuthAttributes(Map<String,Object> attributes, String nameAttributeKey, String name, String email, String picture){
        this.attributes = attributes;
        this.nameAttributeKey = nameAttributeKey;
        this.name = name;
        this.email = email;
        this.picture = picture;
    }

    //사용자 정보는 Map이기 때문에 변경해야함
    public static OAuthAttributes of(String registrationId, String userNameAttributeName, Map<String,Object> attributes){
        return ofGoogle(userNameAttributeName, attributes);
    }

    public static OAuthAttributes ofGoogle(String userNameAttributeName, Map<String,Object> attributes){
        return OAuthAttributes.builder()
                .name((String) attributes.get("name"))
                .email((String) attributes.get("email"))
                .picture((String) attributes.get("picture"))
                .attributes(attributes)
                .nameAttributeKey(userNameAttributeName)
                .build();
    }

    public User toEntity(){
        return User.builder()
                .name(name)
                .email(email)
                .picture(picture)
                .role(Role.GUEST)
                .build();
    }
}

- 서비스에서 사용되는 attribute을 정의한 것