[SB] 소셜로그인 (OAuth2) - Google

0

SpringBoot

목록 보기
4/6

SpringBoot 소셜 로그인 (구글)

Before ...

[ SpringBoot OAuth2 소셜로그인에 대해 알아보자. ]

Google Console

프로젝트 생성


  1. 구글 API 콘솔 접속
  2. 새 프로젝트 생성
  3. OAuth 동의 화면 탭으로 이동
  4. 외부 선택 후 만들기 클릭
  5. 앱 이름, 사용자 지원 이메일 등 필수 칸 입력 후 저장
  6. 생성 완료
  7. 사용자 인증 정보 탭으로 이동
  8. 사용자 인증 정보 만들기 클릭
  9. OAuth Client ID 클릭
  10. 원하는 애플리케이션 유형 선택 후 이름은 자유롭게 설정
  11. 승인된 리다이렉션 URI 입력
    로컬 : ( http://localhost:8080/login/oauth2/code/google )
    배포 : ( http://_Project_URL_/login/oauth2/code/google )
  12. 생성이 완료되면 다음과 같이 클라이언트 ID와 클라이언트 보안 비밀번호를 다운받을 수 있음.

구현 예제

라이브러리 추가

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

application.yml

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: 생성된 클라이언트 ID
            client-secret: 생성된 보안 비밀번호
            scope:
              - email
              - profile

보안을 위해 application.yml에 적어주지 않고 환경변수로 등록하여 사용할 수도 있음.

Memeber Entity에 Column 추가

Member.java

private String provider;
private String providerId;

Principal Details 수정

OAuth2UserDetails.java

public class OAuth2UserDetails implements UserDetails, OAuth2User { 
	
    ... 
    
    private Map<String, Object> attributes;
    
    ...

	public PrincipalDetails(User user, Map<String, Object> attributes) {
    	this.user = user;
    	this.attributes = attributes;
	}
    
    ...
    
    @Override
	public Map<String, Object> getAttributes() {
    	return attributes;
	}
}

OAuth2UserDetails.java

@Service
@RequiredArgsConstructor
@Slf4j
public class Oauth2UserService extends DefaultOAuth2UserService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder encoder;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        log.info("getAttributes : {}", oAuth2User.getAttributes());

        String provider = userRequest.getClientRegistration().getRegistrationId();
        String providerId = oAuth2User.getAttribute("sub");
        String loginId = provider + "_" +providerId;

        Optional<User> optionalUser = userRepository.findByLoginId(loginId);
        User user;

        if(optionalUser.isEmpty()) {
            user = User.builder()
                    .loginId(loginId)
                    .nickname(oAuth2User.getAttribute("name"))
                    .provider(provider)
                    .providerId(providerId)
                    .role(UserRole.USER)
                    .build();
            userRepository.save(user);
        } else {
            user = optionalUser.get();
        }

        return new PrincipalDetails(user, oAuth2User.getAttributes());
    }
}

SecurityConfig 수정

SecurityConfig.java

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final PrincipalOauth2UserService principalOauth2UserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                // 인증
                .antMatchers("/security-login/info").authenticated()
                // 인가
                .antMatchers("/security-login/admin/**").hasAuthority(UserRole.ADMIN.name())
                .anyRequest().permitAll()
                .and()
                // Form Login 방식 적용
                .formLogin()
                // 로그인 할 때 사용할 파라미터들
                .usernameParameter("loginId")
                .passwordParameter("password")
                .loginPage("/security-login/login")     // 로그인 페이지 URL
                .defaultSuccessUrl("/security-login")   // 로그인 성공 시 이동할 URL
                .failureUrl("/security-login/login")    // 로그인 실패 시 이동할 URL
                .and()
                .logout()
                .logoutUrl("/security-login/logout")
                .invalidateHttpSession(true).deleteCookies("JSESSIONID")
                // OAuth 로그인
                .and()
                .oauth2Login()
                .loginPage("/security-login/login")
                .defaultSuccessUrl("/security-login")
                .userInfoEndpoint()
                .userService(principalOauth2UserService)
        ;
        http
                .exceptionHandling()
                .authenticationEntryPoint(new MyAuthenticationEntryPoint())
                .accessDeniedHandler(new MyAccessDeniedHandler());
    }
}
profile
꿈을 계속 간직하고 있으면 반드시 실현할 때가 온다. - 괴테.

0개의 댓글

관련 채용 정보