개발공부/spring security & JWT 강의

[9강] 구글 로그인 및 자동 회원가입 진행 완료

기억지기 개발자 2023. 11. 12. 19:38
@Data
public class PrincipalDetails implements UserDetails, OAuth2User {
    private User user;  //해당 user의 권한을 리턴하는 곳!!
    private Map<String, Object> attribute; //OAuth2 인증 시 사용자의 속성 정보를 저장하기 위해 선언된 필드

    // 일반 로그인 때 사용하는 생성자
    public PrincipalDetails(User user){
        this.user = user;
    }

    //OAuth를 사용하여 로그인하는 생성자
    public PrincipalDetails(User user, Map<String, Object> attribute){
        this.user = user;
        this.attribute = attribute;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new ArrayList<>();
        collection.add((GrantedAuthority) () -> user.getRole());
        return collection;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public String getName() {
        return null;
    }

    @Override
    public Map<String, Object> getAttributes() {
        return attribute;
    }
}

PrincipalDetails 클래스

  • 지난번의 코드와는 다르게 클래스는 일반적인 사용자 정보 및 OAuth2 인증을 모두 다루기 위해 두 가지 인터페이스를 동시에 구현하였다.
  • 일반적인 사용자 정보: UserDetails 인터페이스를 구현하여 일반적인 사용자 정보를 표현합니다. 이 인터페이스는 Spring Security의 인증 및 권한 부여 프로세스에 필요한 사용자 정보를 정의하는 데 사용됩니다. 이러한 정보에는 사용자 이름, 비밀번호, 권한 목록 및 기타 인증과 관련된 정보가 포함됩니다.
  • OAuth2 인증 정보: OAuth2User 인터페이스를 구현하여 OAuth2 기반의 인증 정보를 나타냅니다. OAuth2 인증은 외부 인증 공급자(예: 구글, 페이스북)를 통해 사용자가 로그인하는 경우에 사용됩니다. 
@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {
    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

    @Autowired
    private UserRepository userRepository;

    private static final Logger log = LoggerFactory.getLogger(PrincipalOauth2UserService.class);

    //구글로부터 받은 userRequest 데이터에 대한 후처리되는 함수
    //OAuth2 로그인 요청을 처리하고, OAuth2 공급자(예: 구글)에서 사용자 정보를 가져오는 역할을 수행하는 함수이다.
    // 함수 종료시 @AuthenticationPrincipal 어노테이션이 만들어진다.
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException{
        log.info("getClientRegistration : "+userRequest.getClientRegistration());
        log.info("getAccessToken : "+userRequest.getAccessToken().getTokenValue());

        // DefaultOAuth2UserService를 통해 사용자 정보를 로드하고 OAuth2User 객체를 반환
        OAuth2User oAuth2User = super.loadUser(userRequest);

        // 구글로그인 버튼 클릭 -> 구글 로그인창 -> 로그인을 완료 -> code 리턴(OAuth-Client 라이브러리가 code를 받아줌) -> AccessToken 요청
        // userRequest 정보 -> loadUser 함수 호출 -> 구글로부터 회원프로필 받아줌.
        log.info("getAttributes : "+oAuth2User.getAttributes());

        String provider = userRequest.getClientRegistration().getClientId();
        String providerId = oAuth2User.getAttribute("sub");
        String username = provider + "_" + providerId;
        String password = bCryptPasswordEncoder.encode("TemporaryPasswordKey");
        String email = oAuth2User.getAttribute("email");
        String role = "ROLE_USER";

        User userentity = userRepository.findByUsername(username);
        if(userentity == null) {
            userentity = User.builder()
                    .username(username)
                    .password(password)
                    .email(email)
                    .role(role)
                    .provider(provider)
                    .providerId(providerId)
                    .build();
            userRepository.save(userentity);
        }
        return new PrincipalDetails(userentity, oAuth2User.getAttributes());
    }
}

PrincipalOauth2UserService 클래스

  •  OAuth2 인증을 처리하고 외부 OAuth2 공급자(ex: 구글)로부터 사용자 정보를 가져오는 데 사용된다.
  • @AuthenticationPrincipal 어노테이션은 Spring Security에서 사용되며, 현재 인증된 사용자의 Principal(주체, 즉 현재 로그인한 사용자) 객체를 가져올 때 사용
  • 구글에서 받아온 사용자 정보를 가져와서 우리 프로젝트의 db에 저장하여 관리하도록 하는 코드이다.

 

<< 간단 코드 설명 >>

 oAuth2User.getAttribute("sub"), oAuth2User.getAttribute("email");

여기서 ("     ") 안에 있는 것들이 무엇인가??

바로 아래에 있는 oauth에서 받아온 유저 정보의 필드명 중에 sub와 email이라는 것을 가져와 저장하기 위해서 저렇게 코드를 작성한 것이다.

getAttributes : {sub=[어떤 데이터], name=[어떤 데이터], given_name=[어떤 데이터], family_name=[어떤 데이터], picture=[어떤 데이터], email=[어떤 데이터], email_verified=true, locale=ko}