[ SpringBoot OAuth2 소셜로그인에 대해 알아보자. ]
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
spring:
security:
oauth2:
client:
registration:
google:
client-id: 생성된 클라이언트 ID
client-secret: 생성된 보안 비밀번호
scope:
- email
- profile
보안을 위해 application.yml에 적어주지 않고 환경변수로 등록하여 사용할 수도 있음.
private String provider;
private String providerId;
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;
}
}
@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());
}
}
@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());
}
}