2. 스프링 시큐리티 [OAuth 회원 가입 ]

dasd412·2022년 1월 31일
0

포트폴리오

목록 보기
17/41

엔티티 회원가입 용 생성자 만들기

provider는 OAuth 제공자이고, providerId는 OAuth 제공자가 주는 id이다.

회원가입 시에 엔티티 id 값은 중요하지 않기 때문에 제외한다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    public User(){}

    @Builder
    public User(String username, String password, String email, String role, String provider, String providerId, Timestamp createDate) {
        this.username = username;
        this.password = password;
        this.email = email;
        this.role = role;
        this.provider = provider;
        this.providerId = providerId;
        this.createDate = createDate;
    }

}

OAuth 회원 가입 로직을 추가한다.

DefaultOAuth2UserService를 상속한 서비스 클래스의 loadUser()메서드에 회원 가입 로직을 추가한다.
(단, 이 서비스 클래스는 OAuth2 관련 작업만 처리한다. 사용자 정의 관련 작업은 다른 곳에서 마저 해야 한다.)

loadUser()메서드는 userRequest 데이터에 대해 후처리를 담당해준다.
만약 로딩된 OAuth2User의 username이 서버 리포지토리 내에 없을 경우 save()를 이용해 회원가입을 진행하게 하였다.

이 메서드는 OAuth2User를 리턴하는데, 시큐리티 세션 내의 Authentication 객체가 이 리턴 값을 포함하게 된다.
따라서 이 메서드 실행이 종료되고 나면@AuthenticationPrincipal 어노테이션의 효력이 생긴다.

@Service
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserRepository userRepository;
    
    //구글로부터 받은 userRequest 데이터에 대한 후처리를 담당하는 메서드
    //이 메서드 실행이 종료되고 나서 @AuthenticationPrincipal 어노테이션이 생성된다.
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2User oAuth2User=super.loadUser(userRequest);

        String provider=userRequest.getClientRegistration().getClientId();// google
        String providerId= (String) oAuth2User.getAttributes().get("sub");
        String username=provider+"_"+providerId;//username 은 유니크해야하므로 이와 같이 만듬.
        String password=bCryptPasswordEncoder.encode("겟인데어");//Oauth 로그인일 경우, password는 딱히 의미가 없음.
        String email= (String) oAuth2User.getAttributes().get("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());
    }
}

@AuthenticationPrincipal 어노테이션의 효력이 생긴다.

PrincipalDetails는 UserDetails와 OAuth2User를 모두 implements한 구현체이다.
따라서 @AuthenticationPrincipal 의 효력이 생기고 나면, 해당 구현체는 OAuth 세션 정보도 담을 수 있고 사용자 정의 세션 정보도 담을 수 있게 된다.

//Oauth 로그인을 하던, 일반 로그인을 하던 PrincipalDetails 로 받을 수 있게 되었다.
    @GetMapping("/user")
    public @ResponseBody
    String user(@AuthenticationPrincipal PrincipalDetails principalDetails) {
        System.out.println("principal Details : "+principalDetails.getUser());
        return "user";
    }
profile
시드 레벨 스타트업의 2호 직원으로서 백엔드 시스템의 70%를 설계 및 개발하였고, TIPS 5억 투자 유치에 기여한 서버 개발자입니다. (Go/Python/MSA/Spring)

0개의 댓글