티스토리 뷰

페이스북 OAuth(Open Auth) 등록하기 

구글에서 페이스북 개발자 센터 검색후 해당 페이지 들어가보자

페이지이동 후 오른쪽위 시작하기를 눌러 회원가입을하자 회원가입이 완료되었다면

 

페이스북 API 콘솔에서 애플리케이션 등록 방법

  1. 페이스북 개발자 센터 접속 후 로그인
  2. My Apps -> 앱 만들기
  3. 기타 선택후 다음
  4. 유형 : 소비자 선택
  5. 앱 이름, 이메일, 비지니스 계정 설정 후 앱 만들기
  6. 방금 생성한 앱 대시보드에 접속 후 앱에 제품 추가하기에서 Facebook 로그인 선택
  7. 플랫폼 : 웹 선택
  8. 사이트 URL에 http://localhost:8080 넣어주고 save
  9. 설정 -> 기본설정에서 앱 ID와 앱 시크릿 코드를 저장

왼쪽에 설정의 기본 설정 눌러보면 위와같은 정보가 보일것이다.

이제 yml파일에 등록을해보자

yml파일

    oauth2:
      client:
        registration:
          facebook:
            client-id: 128615706915435
            client-secret: d6bef453b92
            scope:
            - public_profile
            - email

tap을해서 뛰어준뒤 oauth2 적고 자동완성을 하게되면 두개가 보이는대 

OAuth.client.registrations 인것을 선택해주어야한다

registration:까지 생기고 그밑에 난 facebook을 사용하니 facebook라고 명시 (구글이면 google)

바로 위 사진에 보이는 id와 secret를 입력 (secret는 보기하면 보입니다)

스코프

메인페이지의 우측상단 문서의 Facebook로그인을 누르게되면

왼쪽사이드바에 웹이 보일것이다 클릭해주자

 

쭉 내려가보면 scope에 대해 알려주는 글이 보일것이다.

scope는 facebook든 google이든 모두 달라서 확인해주시구 넣어주셔야 합니다.

 

그렇다면 이제 등록은 완성되었다.

 

그렇담 어떤식으로 facebook으로 로그인을하면 내가만든 페이지에도 로그인이 되는걸까?

그림을 표현하면

내홈페이지가 있고 내홈페이지에서 로그인요청을 페이스북으로 하였다

우리가 보통 페이스북 로그인을하면 페이스북에서 실제 사용중인 아이디와 비밀번호를 입력하게된다.

그럼 페이스북아이디와 비밀번호를 입력하면 페이스북에서 데이터를받아 인증을하게되고 맞으면 페이스북이 가지고있는 앱리스트에서 해당하는앱에 승인인증코드를 보내게되고 우리페이지에 로그인이 되는것이다.

 

페이스북 로그인 연동하기

위에서 인증코드를 받았다 그럼 우리서버는 로그인이 됬다는것만 알고 그유저의 데이터는 없는 상태이다 그 데이터를 가져와하는데 이때 그 인증코드를 가지고 facebook에게 인증코드를 들이밀며 해당유저의 데이터를 받아와야한다.

 

이때 유저의 데이터에는 우리가 face문서를 참고해서 알아온 scope에 담긴

email과 public_profile가있다 보면 email은 딱보면 뭔지 알겠다 근데 public_profile는 어떤 데이터가 있는지 모른다

우리가 그 정보를 알아야 그유저의 데이터를 가져와 우리형식에 맞게 User에 입력할 수 있기 때문이다.

 

현재 위와같이 설정하고 서버가 실행되면 에러가 뜨게된다

오류를 해결하기 위해선 데이터를 받아 시큐리티에 지정해줘야한다

 

SecurifyConfig.java

	private final OAuth2DetailsService oAuth2DetailsService;
    
    @Override
	protected void configure(HttpSecurity http) throws Exception {
		// super 삭제 - 기존 시큐리티가 가지고 있는 기능이 다 비활성화됨.
		http.csrf().disable();
		// csrf를 사용하지 않겠다 설정
		
		http.authorizeRequests()
		.antMatchers("/","/user/**","/image/**","/subscribe/**","/comment/**","/api/**").authenticated()
		.anyRequest().permitAll()
		.and()
		.formLogin()
		.loginPage("/auth/signin") // GET
		.loginProcessingUrl("/auth/signin") //POST -> 스프링 시큐리티가 로그인 프로세스 진행
		.defaultSuccessUrl("/")
		.and()
		.oauth2Login() // form로그인도하고 oauth2로그인도 할꺼야
		.userInfoEndpoint() // oauth2로그인을 하면 최종응답을 회원정보로 바로 받을 수 있다.
		.userService(null);
	}

시큐리티에 .and()를 하여 밑의 코드를 추가해주어 oauth2Login()도 사용하고 데이터를 받아오도록 작성되었다

원래는 회원 데이터를 받을때 인증코드를받고 인증코드로 데이터요청하고 반복해야하지만 

.userInfoEndpoint()를 이용하면 한번에 바로 그 유저의 데이터로 접근한다. 

 

위 파이널에 명시된 서비스를 만들자

package com.cos.photogramstart.config.oauth;

import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.stereotype.Service;

@Service
public class OAuth2DetailsService extends DefaultOAuth2UserService{

}

extends DefaultOAuth2userService를 안해주게 되면 Config클래스에서 데이터타입이 다르다고 거부합니다. extends함으로서 해당 데이터타입을 맟줘줬다면 기본 셋팅은 끝나게된다.

 

OAuth2DetailService란?

페이스북 버튼을 클릭하여 페이스북 로그인을한뒤 페이스북에서 그 유저에대한 데이터를 받는곳이 OAuth2DetailsService가 된다.

회원정보가 담기는 공간에서 작업을해주면 데이터를 넣어줄 수 있을거같다.

 

로그인 구현하기

<div class="login__facebook">
    <button onclick="javascript:location.href='/oauth2/authorization/facebook'">
        <i class="fab fa-facebook-square"></i>
        <span>Facebook으로 로그인</span>
    </button>
</div>

버튼의 onclick같이 입력하게되면 페이스북 로그인페이지로 요청이된다

위와같은 정보는 구글에서 밑과같이 검색하고 스프링부트 공식 OAuth2사이트를보면

/auth2/authorization/요청사이트 하게되면 로그인페이지 요청이 된다고 명시되어있다

만약 구글에 요청한다면 /auth2/authorization/google가 되게된다.

서비스에서 데이터 받아오기

@Service
public class OAuth2DetailsService extends DefaultOAuth2UserService{

	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		System.out.println("Oauth2 서비스 탐");
		OAuth2User oAuth2User = super.loadUser(userRequest);
		System.out.println(oAuth2User.getAttributes());
		return null; 
	}
}

페이스북에서 넘어온 값은 super.loadUser에 담기게되고 

OAuth2User을 getAttributes()를 하게되면 안의 값 모든게 출력이된다 확인해보니 데이터의 형태는 이러하다.

그렇다면 위의 데이터를 보면 yml에 명시하였던 pblic_profile는 id와 name데이터가 있고

email에 이메일데이터가 있는걸 알 수가 있다(페이스북은 총3개의 데이터를 주고있다)

 

주의

확인하실때 페이스북 꼭 로그아웃하고 확인해보셔야합니다 안그럼 데이터 매핑이안된다고 에러가 계속나옵니다.

 

이제 데이터를 받아왔으니 DB에 등록하고 로그인시켜보자

OAuth2DetailsService.java

package com.cos.photogramstart.config.oauth;

@RequiredArgsConstructor
@Service
public class OAuth2DetailsService extends DefaultOAuth2UserService{

	private final UserRepository userRepository;
	private final BCryptPasswordEncoder bCryptPasswordEncoder;
	
	@Override   	 			// 페이스북에서 받은 데이터
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		
		// 받은 데이터를 OAuth2User에 저장
		OAuth2User oAuth2User = super.loadUser(userRequest);
		
//		System.out.println(oAuth2User.getAttributes()); // 어떤데이터가 담겨오는지 확인
		
		// 모든 데이터를 맵 형태로 value에는 모든데이터가 가능하게 Object로 받음
		Map<String, Object> userinfo = oAuth2User.getAttributes();
		
		// 데이터를 받을땐 String로 다운캐스팅 해주자.
		String username = "facebook_"+(String) userinfo.get("id");
		// 사용하진 않을거지만 UUID를 이용해 암호를 넣어줌
		String password = bCryptPasswordEncoder.encode(UUID.randomUUID().toString());
		String email = (String) userinfo.get("email");
		String name = (String) userinfo.get("name");
		
		// DB에서 데이터를 조회
		User userEntity = userRepository.findByUsername(username);
		
		// 데이터가 없다면 build시켜줌
		if(userEntity == null) { // 최초 로그인
			User user = User.builder()
					.username(username)
					.password(password)
					.name(name)
					.email(email)
                    .role("ROLE_USER")
					.build();
			// 처음 페북로그인이라면 DB에저장후 세션에등록
			return new PrincipalDetails(userRepository.save(user), oAuth2User.getAttributes());
			
			// 이미 페이스북으로 로그인한적이있어 DB에 username이 있다면 DB에 데이터를 넣지않고
			// 바로 로그인 시켜주게된다.
		}else { 
			return new PrincipalDetails(userEntity, oAuth2User.getAttributes());
		}
	}
}

위에 코드를 보면 이상하지 않은가?

PrincipalDetails에 매개변수를 두개나 넣어주고있다 왜그런지는 밑의 글을보면서 알아보자

 

우선 PrincipalDetails에 implements에 OAuth2User추가와 생성자를 추가하였다

@Data
public class PrincipalDetails implements UserDetails,OAuth2User{
	
	private static final long serialVersionUID = 1L;

	private User user;
	private Map<String, Object>  attributes;
	
	public PrincipalDetails(User user) {
		this.user = user;
	}
	
	public PrincipalDetails(User user,Map<String, Object> attributes) {
		this.user = user;
	}

왜그런것일까?

OAuth2Details자료도 PrincipalDetails화 시키기 위해서이다.

무슨말이냐 하면 페이스북 로그인하면 세션을 만들어줘야하는데 OAuth2PrincipalDetails라는 세션을 만들어주는 클래스를 만들었다 우리가 사용하고있는 PrincipalDetails과 형식은 같을것이다 그렇담 여기서 문제는 이사람이 페이스북으로 로그인할지 아니면 그냥 웹페이지 로그인을 할지 모른다 그럼 그때마다 일일이 처리해줘야할까? 절대아니다

OAuth2Details와 PrincipalDetails를 묶어서 똑같이 PrincipalDetails를 사용해서 세션에 추가해주면 되는것이다

그러기위해선 implements에 OAuth2User을 추가하게되면 

밑의 두개의 함수가 추가될것이다

	// OAuth2User에 의해 추가된 함수 2개
	@Override
	public Map<String, Object> getAttributes() {
		return attributes; // 페이스북에서 넘어온 데이터
	}

	@Override
	public String getName() {
		return (String)attributes.get("name");
	}

그럼 위와같이 작성하고 

Map에는 아까 출력해봤던 {id=4124125151251, name=홍길동, email=kkkko371@naver.com}

형식으로 데이터가 있을거고

 

name에는 홍길동만 들어가게될것이다 (Object형식이라 String로 다운캐스팅 해주었다)

 

그리고 한가지더 알아야 할점은 만약 유저의 데이터를 조회했는데

User의정보만있다면 그냥 로그인이고

map<String,Object>의 자료도 가지고있다면 OAuth로그인사용자이구나를 알수도있다

또 위와같이 간단하게 생성자하나 추가해주고 implement만 해주면 principal로 묶을수 있는걸 기억하자.

 

di오류

OAuth2DetailsService에서 BCryptPasswordEncoder를 불러와 비밀번호 암호화 한것이 기억날것이다 코드로 가보자

	// 필드
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    
     // 함수안
     String password = bCryptPasswordEncoder.encode(UUID.randomUUID().toString());

형태로 사용되고있는데 에러가 발생하였다 그래서 밑과 같이 코드를 수정하니 에러가 사라졌다.

// 함수안
String password = new BCryptPasswordEncoder().encode(UUID.randomUUID().toString());

 

에러의 내용은 대충 이러하였다

dependencies문제라고 표기되어있고

우리가 di한 BCryptpasswordEncoder를 불러올때 securifyConfig가 불러와지고 OAuth2DetailsService가 불러와져야하는데 securityConfig가 더 늦게불러와지니 에러가 발생한다 

즉 ioc에 OAuth2DetailsService가 등록되서 securityConfig의 encode를 불러와야하는데 아직 ioc에 securityConfig가 등록이안되었으니 불러오질 못해 에러가 발생한것이다.

그래서 new로 BCryptPasswordEncoder()을 불러오면 해결이된다.

 

username 크기 오류

로그인해보니 data long column username이라고 발생하였다 username이 너무 길다는것이다 우리가 우리 웹페이지에서만 생각하여 크기를 20으로 설정하였지만 다른 로그인서비스를 이용할 경우 이점도 생각해봐야한다 데이터가 어떻게 넘어오고 크기는 어느정도인지 원인을 알았으니 크기를 늘려주자.

User.java

	@Column(length=100 , unique  = true) // OAuth2 로그인을 위해 칼럼 늘리기
	private String username;

스키마가 변경된것이니 yml에서 update를 create로 바꿔주자.

 

DB에 스키마가 변경된걸 확인하고 페이스북 로그인을하니 데이터가 잘 들어간것이 확인되었다

페이스북 로그인 구현하기 끝이나게 된다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함