로그인이 완료된 다음에 구글이 어떤 것을 돌려줄까?
1. 코드 받기
인증이 되었다는 뜻, 코드를 받았으니까 로그인이 되었다는 의미. 이 사람이 구글로 로그인한 정상적인 사람이라는 것이다.
2. 엑세스 토큰받기
우리 시큐리티 서버가 구글 사용자 정보에 접근할 수 있는 권한이 생기는 것이다.
3. 사용자 프로필 정보를 가져온다.
4-1. 정보를 토대로 회원가입을 자동으로 진행시킨다.
4-2.
만약 그 정보가 조금 모자랄때.. 무슨 의미냐면 내가 만약 쇼핑몰 사이트를 운영하는데 (이메일, 전화번호, 이름, 아이디) 밖에 없다고 하자. 그럼 쇼핑몰에서는 추가적으로 집 주소가 필요한데.. 혹은 백화점몰이라면 vip등급, 일반등급도 필요하다. 추가적인 구성들이 필요하게 되면 추가적인 회원가입 창이 나와서 회원가입을 해야 한다. 만약 이런 것들이 필요없다면 그냥 (이메일, 전화번호, 이름, 아이디) 이것만 있으면 자동으로 회원가입을 진행시키면 된다. 우리는 그 정보를 가져와서 회원가입을 자동으로 진행시킬 것이다.
Tip.
코드가 아니라 엑세스토큰+사용자 프로필 정보를 한방에 받을 수 있다. 따라서 oauth 클라이언트 라이브러리를 사용하면 굉장히 편리하다.
config 안에 ouath 패키지를 만든다. 그리고 PrincipalOauth2UserService.java를 생성한다. 얘는 타입이
DefaultOAuth2UserService 가 되어야 한다.
PrincipalOauth2UserService.java
package com.yuri.security1.config.oauth;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService{
// 구글로부터 받은 userRequest 데이터에 대한 후처리 되는 함수
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
System.out.println("getClientRegistration : " + userRequest.getClientRegistration());
System.out.println("getAccessToken : " +userRequest.getAccessToken().getTokenValue());
System.out.println("getAttribute : " +super.loadUser(userRequest).getAttributes());
return super.loadUser(userRequest);
}
}
loadUser라는 함수에 의해 후처리가 일어난다.
그럼 userRequest 는 무엇을 갖고 있는 것일까?....
getClientRegistration : ClientRegistration{registrationId='google', clientId='774158704369-5ckg8m14n6p5oqqfa9o3ar29ednsuroo.apps.googleusercontent.com', clientSecret='Ii2YP2RY0aKLXNHhyCU9a8Tr', clientAuthenticationMethod=org.springframework.security.oauth2.core.ClientAuthenticationMethod@592d42e, authorizationGrantType=org.springframework.security.oauth2.core.AuthorizationGrantType@5da5e9f3, redirectUriTemplate='{baseUrl}/{action}/oauth2/code/{registrationId}', scopes=[email, profile], providerDetails=org.springframework.security.oauth2.client.registration.ClientRegistration$ProviderDetails@56fbbfbd, clientName='Google'}
getAccessToken : ya29.a0AfH6SMDpRWL5Hyc_jw0CwrQYEp-50-ra-LbVfLkFwuBOH277RPNdCsZqCaYcDZ6_i3qp2ZrRe0wvz0xgPMiPUK3ctkS0i_e_IKZumY08N6xKKwSOKPvAA-NIwkS9tcOr0Cyl9cOgmYdYdxidS28Cv_4KZQoJdlnq3IM
getAttribute : {sub=108093779182714031698, name=yuri lee, given_name=yuri, family_name=lee, picture=https://lh3.googleusercontent.com/-wYB_5cdsgPY/AAAAAAAAAAI/AAAAAAAAACs/AMZuuckiu3V1IB3F_MHAmtcJnp1Ih_hq4w/photo.jpg, email=ddddd@gmail.com, email_verified=true, locale=en}
우리는 엑세스 토큰이 필요가 없다. 엑세스 토큰은 이미 사용자 프로필 정보에 들어있기 때문에 ..
{sub=108093779182714031698,
name=yuri lee,
given_name=yuri,
family_name=lee, picture=https://lh3.googleusercontent.com/-wYB_5cdsgPY/AAAAAAAAAAI/AAAAAAAAACs/AMZuuckiu3V1IB3F_MHAmtcJnp1Ih_hq4w/photo.jpg, email=dddd@gmail.com,
email_verified=true,
locale=en}
sub=108093779182714031698 는 구글에 가입한 아이디 넘버 primary number 과 같은 것임
User.java
package com.yuri.security1.model;
import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.CreationTimestamp;
import lombok.Data;
@Entity
@Data
public class User {
@Id // primary key
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private String email;
private String role; //ROLE_USER, ROLE_ADMIN
@CreationTimestamp
private Timestamp createDate;
}
username = "google_108093779182714031698" // 중복될 일이 없다. 이렇게 하면..
password = "암호화(유리유리)" // 우리 서버 안에는 유리유리를 암호화해서 넣을 것이다. 어차피 이 회원은 구글 로그인으로 진행되어서 되는 회원이지 아이디나 비번을 쳐서 가입하는 게 아니다. 따라서 이 암호는 null 만 넣지 않고 아무거나 넣어도 상관없다.
email = "dddd@gmail.com" // 그대로 사용
role = ROLE_USER
provider = "google"
providerId ="108093779182714031698" // 구글에서 받은 아이디
이렇게만 하면 얘가 일반적인 사용자인지 oauth를 사용한 사용자인지 구분할 수 없다. 그래서 user object (User.java) 밑에다가 필드를 추가하자.
private String provider;
private String providerId;
super.loadUser(userRequest).getAttributes()이 정보로 강제 회원가입을 시킬 것이다. 이 getAttributes 정보를 토대로 다음시간에는 회원가입을 강제로 진행해볼 것이다.
[Reference]
이 글은 유투버 데어 프로그래밍의 스프링 부트 시큐리티 강좌를 바탕으로 정리한 내용입니다.