- 페이스북 개발자 콘솔에 접속
- 내 앱에서 새 앱 추가
- 앱 유형은 없음
- 로그인 api선택
- 웹 선택 후 url 입력
- 이후에는 계속만 누르면 된다!
- 기본설정에서 id/password확인
Application.properties 코드 추가
#페이스북
spring.security.oauth2.client.registration.facebook.client-id=클라이언트id
spring.security.oauth2.client.registration.facebook.client-secret=클라이언트 password
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.registration.facebook.authorization-uri=/oauth2/authorization/google
...
<a href="/oauth2/authorization/facebook">페이스북 로그인</a></br>
...
- 이제 페이스북 로그인을 해보면 아래처럼 user정보를 가져오는 것을 확인할 수 있다.
getClientRegistration : ClientRegistration{registrationId='facebook',
clientId='1215126159139044', clientSecret='522edf8dcc59a5165a50dd4546fd011f',
clientAuthenticationMethod=org.springframework.security.oauth2.core.ClientAuthenticationMethod@86baaa5b,
authorizationGrantType=org.springframework.security.oauth2.core.AuthorizationGrantType@5da5e9f3,
redirectUri='{baseUrl}/{action}/oauth2/code/{registrationId}',
scopes=[email, public_profile], providerDetails=org.springframework.security.oauth2.client.registration.ClientRegistration$ProviderDetails@58ef59ed, clientName='Facebook'}
getAccessToken = EAARRJpsSoOQBACsiBd8FtIeQxDT2DTU0vZAE8ZAOrjCQQRgFZC9JTpTE8Tv5HcMZBKOmKc9vOLwQz7vnGIWe2JT6Mbg5f79cD3tIvVQpXjaD3lMvUTk4YqMlyiUJCoOhJjRAYWvRp0zKUkU1d1hdgaWpv5TKr2PUG5OLtMMJf38NZBlGtpFzh4XM0ywS8LGSyEMPnapmbBSlsLP6bitCOtBKpubrrWoqJz5BKRBedmwZDZD
getAttributes = {id=3120786284720769, name=박의민, email=magicofclown@naver.com}
- 그런데 DB에서 user 테이블을 검색해보면 provider에 "facebook"이 아닌 다른 값이 찍힌다.
- 이건 앞의 글에서 이미 수정했으므로 따로 신경쓰지 않아도 된다
PrincipalOauth2UserService 수정
- PrincipalOauth2UserService의 loadUser를 수정해주자
- String provider만 수정해주면 된다.
- 이건 앞의 글에서 이미 수정했으므로 따로 신경쓰지 않아도 된다
// 회원가입을 강제로 진행해볼 예점
String provider = userRequest.getClientRegistration().getRegistrationId(); // google
// getClientId에서 getRegistrationId로 바뀜
System.out.println("provider = " + provider);
// 그리고 provider의 값을 다시 확인해보자
- Application.properties의 spring.jpa.hibernate.ddl-auto값을 create로 설정해서 프로젝트를 시작하고 다시 update로 바꿔서 프로젝트를 재시작해주자.
- 그리고 다시 페이스북 로그인을 시도해보면 provider로 facebook이 찍히는 걸 확인해 볼 수 있다.
- 그런데 구글에서는 providerId값이 sub로 넘어오는 반면에 페이스북에서는 id라는 값으로 넘어온다. 때문에 유지보수를 고려해 따로 처리해줄 interface와 구현체를 생성해주자!!
OAuth2UserInfo 생성
- oauth패키지에 provider패키지를 생성하고 OAuth2UserInfo인터페이스를 생성해주자
package com.cos.security1.config.oauth.provider;
public interface OAuth2UserInfo {
String getProviderId(); // 도메인에서 부여한 id값
String getProvider(); // 도메인
String getEmail(); // 클라이언트 email
String getName(); // 클라이언트 이름
}
OAuth2UserInfo 구현체 생성
GoogleUserInfo 클래스 생성
package com.cos.security1.config.oauth.provider;
import java.util.Map;
public class GoogleUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes; // oAuth2User.getAttributes()
public GoogleUserInfo(Map<String, Object> attributes) {
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String) attributes.get("sub");
}
@Override
public String getProvider() {
return "google";
}
@Override
public String getEmail() {
return (String) attributes.get("email");
}
@Override
public String getName() {
return (String) attributes.get("name");
}
}
FacebookUserInfo 클래스 생성
package com.cos.security1.config.oauth.provider;
import java.util.Map;
public class FacebookUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes; // oAuth2User.getAttributes()
public FacebookUserInfo(Map<String, Object> attributes) {
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String) attributes.get("id");
}
@Override
public String getProvider() {
return "facebook";
}
@Override
public String getEmail() {
return (String) attributes.get("email");
}
@Override
public String getName() {
return (String) attributes.get("name");
}
}
PrincipalOauth2UserService 수정
- 이제 google과 facebook로그인에 따라 값을 처리해주자
@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private UserRepository userRepository;
// 구글로부터 받은 userRequest 데이터에 대한 후처리가 되는 함수
// 해당 함수 종료시에 @Authentication이 만들어진다!!!
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// registrationId로 어떤 oauth로 로그인 했는지 알 수 있음
System.out.println("getClientRegistration : " + userRequest.getClientRegistration());
System.out.println("getAccessToken = " + userRequest.getAccessToken().getTokenValue());
OAuth2User oAuth2User = super.loadUser(userRequest);
// 구글 로그인 버튼 클릭 -> 구글 로그인 창 -> 로그인을 완료 -> code를 리턴(Oauth-client라이브러리 -> AccessToken 요청
// userRequest정보 -> loadUser함수 호출 -> 구글로부터 회원 프로필을 받아줌
System.out.println("getAttributes = " + super.loadUser(userRequest).getAttributes());
// ****이부분이 바뀜****
// 회원가입을 강제로 진행해볼 예점
OAuth2UserInfo oAuth2UserInfo = null;
if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
System.out.println("구글 로그인 요청");
oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
} else if (userRequest.getClientRegistration().getRegistrationId().equals("facebook")) {
System.out.println("페이스북 로그인 요청");
oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
} else {
System.out.println("우리는 구글과 페이스북만 지원해요!!!");
}
String provider = oAuth2UserInfo.getProvider();
String providerId = oAuth2UserInfo.getProviderId();
String username = provider + "_" + providerId; // google_105156291955329144943
String password = bCryptPasswordEncoder.encode("겟인데어");
String email = oAuth2UserInfo.getEmail();
String role = "ROLE_USER";
// 회원 중복 체크
User userEntity = userRepository.findByUsername(username);
if (userEntity == null) {
System.out.println("로그인이 최초입니다.");
userEntity = User.builder()
.username(username)
.password(password)
.email(email)
.role(role)
.provider(provider)
.providerId(providerId)
.build();
userRepository.save(userEntity);
}else {
System.out.println("로그인을 이미 한적이 있습니다. 당신은 자동회원가입이 되어 있습니다.");
}
return new PrincipalDetails(userEntity, oAuth2User.getAttributes());
}
}
- 이렇게 하면 google, facebook에 상관없이 oAuth2UserInfo를 통해서 값을 처리할 수 있게 된다!!
- 다시 Application.properties의 spring.jpa.hibernate.ddl-auto설정을 이용해 db를 초기화해주자.(create후 update로 수정)
- 이제 구글, 페이스북, 일반 로그인을 하고 DB를 확인해보자!
값들이 제대로 들어간 것을 확인할 수 있다.
- 또한 provider값이 있는지 없는지에 따라 일반 로그인과 OAuth2를 이용한 로그인을 구분할 수 있다
- 이걸로 Facebook로그인도 구현해 보았다!!