ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 네이버 로그인
    스프링 2023. 12. 31. 17:53

    Properties

     

    spring.security.oauth2.client.registration.naver.client-id = 
    spring.security.oauth2.client.registration.naver.client-secret = 
    spring.security.oauth2.client.registration.naver.redirect-uri = 
    spring.security.oauth2.client.registration.naver.authorization-grant-type = authorization_code
    spring.security.oauth2.client.registration.naver.scope = nickname,email,profile_image
    spring.security.oauth2.client.registration.naver.client-name = Naver
    spring.security.oauth2.client.provider.naver.authorization-uri = https://nid.naver.com/oauth2.0/authorize
    spring.security.oauth2.client.provider.naver.token-uri = https://nid.naver.com/oauth2.0/token
    spring.security.oauth2.client.provider.naver.user-info-uri = https://openapi.naver.com/v1/nid/me
    # 회원정보를 json으로 받는데 response라는 키값으로 네이버가 return해줌.(value에는 getAttributes()한 값들이 들어가있음)
    spring.security.oauth2.client.provider.naver.user-name-attribute = id


    Controller

     

    @RestController
    @Slf4j
    @RequiredArgsConstructor
    public class NaverController {
        private final NaverUserService naverUserService;

        @GetMapping("api/user/naver/callback")
        public ResponseEntity<Message> naverLogin(@RequestParam String code, String state, HttpServletResponse response) throws JsonProcessingException {
            return naverUserService.naverLogin(code, state, response);
        }
    }


    NaverUserInfoDto

     

    @Getter
    public class NaverUserInfoDto {
        private Long id;
        private String nickName;
        private String email;
        private String profileImage;

        public NaverUserInfoDto(Long id, String nickname, String email, String profileImage) {
            this.id = id;
            this.nickName = nickname;
            this.email = email;
            this.profileImage = profileImage;
        }
    }


    Service

     

    @Slf4j
    @Service
    @RequiredArgsConstructor
    public class NaverUserService {
        private final PasswordEncoder passwordEncoder;
        private final UserRepository userRepository;
        private final JwtUtil jwtUtil;

        @Value("${spring.security.oauth2.client.registration.naver.client-id}")
        private String naverClientId;
        @Value("${spring.security.oauth2.client.registration.naver.client-secret}")
        private String naverClientSecret;
        @Value("${spring.security.oauth2.client.registration.naver.redirect-uri}")
        private String naverRedirectUri;

        public ResponseEntity<Message> naverLogin(String code, String state, HttpServletResponse response) throws JsonProcessingException {
            // 인가코드, state 로 네이버한테 access_token 요청
            String accessToken = getToken(code, state);

            // access_token 으로 사용자 정보 가져오기
            NaverUserInfoDto naverUserInfoDto = getNaverUserinfo(accessToken);

            // 회원가입
            User naverUser = registerNaverUser(naverUserInfoDto);

            // 토큰 헤더에 담기
            jwtUtil.createAndSetToken(response, naverUser.getEmail(), naverUser.getId());

            return new ResponseEntity<>(new Message("네이버 로그인", naverUserInfoDto.getNickName()),HttpStatus.OK);
        }
        //  https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=N67sIS7i6jSW96HgtEcW&redirect_uri=http://localhost:8080/api/user/naver/callback&state=state

        private String getToken(String code, String state) throws JsonProcessingException {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

            MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
            body.add("grant_type", "authorization_code");
            body.add("client_id", naverClientId);
            body.add("client_secret", naverClientSecret);
            body.add("redirect_uri", naverRedirectUri);
            body.add("code", code);
            body.add("state", state);

            HttpEntity<MultiValueMap<String, String>> naverTokenRequest =
                    new HttpEntity<>(body, headers);
            RestTemplate rt = new RestTemplate();
            ResponseEntity<String> response = rt.exchange(
                    "https://nid.naver.com/oauth2.0/token",
                    HttpMethod.POST,
                    naverTokenRequest,
                    String.class
            );

            // HTTP 응답 (JSON) -> 액세스 토큰
            String responseBody = response.getBody();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            return jsonNode.get("access_token").asText();
        }

        private NaverUserInfoDto getNaverUserinfo(String accessToken) throws JsonProcessingException {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Bearer " + accessToken);
            headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

            // HTTP 요청 보내기
            HttpEntity<MultiValueMap<String, String>> naverUserInfoRequest = new HttpEntity<>(headers);
            RestTemplate rt = new RestTemplate();
            ResponseEntity<String> response = rt.exchange(
                    "https://openapi.naver.com/v1/nid/me",
                    HttpMethod.POST,
                    naverUserInfoRequest,
                    String.class
            );

            String responseBody = response.getBody();
            ObjectMapper objectMapper2 = new ObjectMapper();
            JsonNode jsonNode2 = objectMapper2.readTree(responseBody).get("response");

            Long id = jsonNode2.get("id").asLong();
            String nickname = jsonNode2.get("name").asText();
            String email = jsonNode2.get("email").asText();
            String profileImage = jsonNode2.get("profile_image").asText();

            log.info("네이버 사용자 정보: " + id + ", " + nickname + ", " + email + ", " + profileImage);
            return new NaverUserInfoDto(id, nickname, email, profileImage);
        }

        @SneakyThrows
        private User registerNaverUser(NaverUserInfoDto naverUserInfoDto) {
            Long naverId = naverUserInfoDto.getId();
            String profileImage = naverUserInfoDto.getProfileImage();
            User naverUser = userRepository.findByNaverId(naverId).orElse(null);
            Random random = SecureRandom.getInstanceStrong();

            if (naverUser == null) {
                Long navernewId = random.nextLong();
                String naverEmail = naverUserInfoDto.getEmail();
                User sameEmailUser = userRepository.findByEmail(naverEmail).orElse(null);
                if (sameEmailUser != null) {
                    naverUser = sameEmailUser;
                    naverUser = naverUser.naverUpdate(navernewId, profileImage);
                } else {
                    String password = UUID.randomUUID().toString();
                    String encodePassword = passwordEncoder.encode(password);
                    String email = naverUserInfoDto.getEmail();

                    naverUser = new User(null, navernewId, null, email, naverUserInfoDto.getNickName(), encodePassword, profileImage, UserRoleEnum.USER);
                }
                userRepository.save(naverUser);
            }
            return naverUser;
        }
    }

     

     

    '스프링' 카테고리의 다른 글

    CORS  (0) 2024.03.18
    구글 로그인  (0) 2023.12.31
    카카오 로그인  (0) 2023.12.31
    DB접속  (0) 2023.12.31
    스프링 부트 (회원가입,로그인,토큰발급)api명세서  (0) 2023.04.25
Designed by Tistory.