1. 구글 로그인 API 토큰 발급
https://cloud.google.com/?hl=ko
새 프로젝트 생성
프로젝트 생성 후 왼쪽 메뉴에서 OAuth 동의 화면 클릭
외부 선택 후 만들기
앱 등록정보에서 필수 입력값만 입력 후 다음
범위 추가 또는 삭제 선택 후 위 3개 (email, profile, openid만 선택)
사용자 인증 정보 선택 후 사용할 url 입력하기
모든 과정을 완료했으면 클라이언트 ID 및 secret key를 발급받을 수 있다.
2. SpringBoot에 Google 로그인 API 연동
먼저 oauth 사용을 위한 설정 파일을 생성합니다.
!주의 github에 프로젝트를 관리한다면 이런 secret key가 포함된 파일은 ignore 해주어야 합니다. (private은 상관없음)
spring:
security:
oauth2:
client:
registration:
google:
client-id: 발급받은 ID
client-secret: 발급받은 key
scope: profile,email
그리고 기존에 있던 application.yml 파일에
spring.profiles.include: oauth를 추가해 줍니다.
gradle 설정
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Config파일 설정
config파일에서 url에 따른 권한 설정이나 로그아웃 후 처리, 로그인 처리 등을 설정할 수 있습니다.
예전에는 WebSecurityConfigurerAdapter를 상속받아서 configure 메소드를 오버라이딩 하여 사용했지만 현재는 deprecated 되었고 filterChain 사용을 권장하고 있습니다.
@RequiredArgsConstructor
@EnableWebSecurity // spring security 설정 활성화
public class SecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf().disable().headers().frameOptions().disable() // h2-console을 사용하기 위해 옵션 disable
.and()
.authorizeRequests().antMatchers("/", "/css/**", "/images/**", "/js/**", "/h2-console/**").permitAll()
.antMatchers("/api/v1/**").hasRole(Role.USER.name()) // 권한 관리 대상, USER 권한을 갖는 사람만 가능하도록
.anyRequest().authenticated() // 나머지 URL은 로그인한 사용자들에게 허용
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.oauth2Login()
.userInfoEndpoint()
.userService(customOAuth2UserService).and().and().build(); // 로그인 성공 후 후속조치
}
}
그 다음 구글 로그인 API 를 통해 받은 유저를 등록할 Entity를 생성합니다.
@Getter
@NoArgsConstructor
@Entity
public class Member extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
@Column
private String picture;
@Enumerated(EnumType.STRING) // Enum 값을 어떤 형태로 정할지 결정, default = int
@Column(nullable = false)
private Role role;
@Builder
public Member(String name, String email, String picture, Role role) {
this.name = name;
this.email = email;
this.picture = picture;
this.role = role;
}
public Member update(String name, String picture) {
this.name = name;
this.picture = picture;
return this;
}
public String getRoleKey() {
return this.role.getKey();
}
}
OAuth2UserService 생성
OAuth2를 사용해 로그인 후 user 정보를 세팅하는 클래스를 생성합니다.
@RequiredArgsConstructor
@Service
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();
OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());
Member member = saveOrUpdate(attributes);
httpSession.setAttribute("user", new SessionUser(member)); // 세션에 저장
return new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority(member.getRoleKey())), attributes.getAttributes(), attributes.getNameAttributeKey());
}
private Member saveOrUpdate(OAuthAttributes attributes) {
Member member = userRepository.findByEmail(attributes.getEmail())
.map(entity -> entity.update(attributes.getName(), attributes.getPicture()))
.orElse(attributes.toEntity());
return userRepository.save(member);
}
}
'Java > Spring' 카테고리의 다른 글
[SpringBoot] Spring Security 네이버 로그인 연동 (0) | 2023.09.13 |
---|---|
[Spring Boot] 스프링 부트 mustache 한글 깨짐 현상 (0) | 2023.08.08 |
[SpringBoot] SpringBoot에서 JPA 사용하기 (0) | 2023.08.05 |
[Spring] JPA 란 무엇인가 (정의, 장단점) (0) | 2023.06.01 |
Springboot 환경에서 @Async와 ThreadPoolTaskExecutor (0) | 2023.05.26 |