Spring Security 페이스북 로그인

바그다드·2023년 4월 8일
0

Spring Security

목록 보기
10/17
  1. 페이스북 개발자 콘솔에 접속
  2. 내 앱에서 새 앱 추가
  3. 앱 유형은 없음
  4. 로그인 api선택
  5. 웹 선택 후 url 입력
    - 이후에는 계속만 누르면 된다!
  6. 기본설정에서 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

loginForm.html 수정

  • 페이스북 로그인 버튼을 추가해주자
...
<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로그인도 구현해 보았다!!
profile
꾸준히 하자!

0개의 댓글