深化クラス-2週目-3


2022年4月16日(土)
[スパルタコードクラブ]Spring深化クラス-2週間-3

◇ソーシャルログイン

  • OAuth:インターネットユーザーがパスワードを提供することなく、Webサイトまたはアプリケーション上の情報にアクセスすることを許可するためのオープン・スタンダード.
  • ユーザー 您可以通过 HTTPベースのセキュリティプロトコル
    ex)KACA、NAVER、グーグル、Facebook…
  • ◇Kakaoでの登録許可取得

  • KACAログイン使用承認基本アーキテクチャ
  • マイアプリケーションの追加>アプリケーション
  • 登録
  • サイトドメイン:アプリケーションの選択>テーブルメニューの選択>Webプラットフォームの登録>サイトドメインの入力(http://localhost:8080)
  • KACA登録時に承認トークンを受信ダイレクトURI(コールバック)
  • を設定する.
  • 同意の項目設定:個人情報、KACAアカウント(電子メール)などを受信できます.
  • ◇カカオユーザー情報取得

  • KACA認証コード取得(フロントにて設定)
  • https://kauth.kakao.com/oauth/authorize?client_id=본인의 REST API키&redirect_uri={REDIRECT_URI}&response_type=code
  • 認証コード受信時処理
  • @GetMapping("/user/kakao/callback")
    public String kakaoLogin(@RequestParam String code) {
        // authorizedCode: 카카오 서버로부터 받은 인가 코드
        KakaoUserService.kakaoLogin(code); // userService.kakaoLogin 에서 나머지 처리
        return "redirect:/";
    }
  • KACAユーザ情報のインポート
  • 「認証コード」要求「アクセストークン」
  • public void kakaoLogin(String code) throws JsonProcessingException {
    	    // 1. "인가 코드"로 "액세스 토큰" 요청
            // HTTP Header 생성
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
    
            // HTTP Body 생성
            MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
            body.add("grant_type", "authorization_code");
            body.add("client_id", "본인의 REST API키");
            body.add("redirect_uri", "http://localhost:8080/user/kakao/callback");
            body.add("code", code);
    
            // HTTP 요청 보내기
            HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest =
                    new HttpEntity<>(body, headers);
            RestTemplate rt = new RestTemplate();
            ResponseEntity<String> response = rt.exchange(
                    "https://kauth.kakao.com/oauth/token",
                    HttpMethod.POST,
                    kakaoTokenRequest,
                    String.class
            );
    
            // HTTP 응답 (JSON) -> 액세스 토큰 파싱
            String responseBody = response.getBody();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            String accessToken = jsonNode.get("access_token").asText();
    }
  • 「アクセストークン」は「カカオユーザ情報」
  • にインポートする.
    		// 2. 토큰으로 카카오 API 호출
            // HTTP Header 생성
            headers.add("Authorization", "Bearer " + accessToken);
            headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
    
            // HTTP 요청 보내기
            HttpEntity<MultiValueMap<String, String>> kakaoUserInfoRequest = new HttpEntity<>(headers);
            response = rt.exchange(
                    "https://kapi.kakao.com/v2/user/me",
                    HttpMethod.POST,
                    kakaoUserInfoRequest,
                    String.class
            );
    
            responseBody = response.getBody();
            jsonNode = objectMapper.readTree(responseBody);
            Long id = jsonNode.get("id").asLong();
            String nickname = jsonNode.get("properties")
                    .get("nickname").asText();
            String email = jsonNode.get("kakao_account")
                    .get("email").asText();
    
            System.out.println("카카오 사용자 정보: " + id + ", " + nickname + ", " + email);
  • 再パッケージ(特定の部分を関数化してスキップ)
  • 「アクセストークンの要求」を「承認コード」の部分「
  • 」にドラッグします.
  • 右クリック>ファクタ>終了方法(ショートカットキーCtrl+Alt+M)
  • 動作が正常であることを確認します!
  • 「アクセストークンの使用」「カカオユーザ情報のインポート」セクションでは、同じExtractメソッドを使用して
  • を取得することもできる.

    ◇KACAユーザー情報を利用して会員加入


  • 設計:誰もがさまざまな操作を実行できますが、次の項目では次のことができます.
  • KakaoId Columnの追加:Kakaoに参加したユーザーが「KakaoId」文字列
  • を追加
  • パスワードは、UUID(ランダムに生成する文字列)を
  • に符号化する.
  • その他の注意事項は、コード
  • を参照してください.

  • UserテーブルにkakaoIdを追加(nullable true,unique true)

  • 会員加入:KakaoId会員がいない場合のみ会員加入
  • 				// DB 에 중복된 Kakao Id 가 있는지 확인
            Long kakaoId = kakaoUserInfo.getId();
            User kakaoUser = userRepository.findByKakaoId(kakaoId)
                    .orElse(null); // UserRepository 설정 해주어야 함
            if (kakaoUser == null) {
                // 회원가입
                // username: kakao nickname
                String nickname = kakaoUserInfo.getNickname();
    
                // password: random UUID
                String password = UUID.randomUUID().toString();
                String encodedPassword = passwordEncoder.encode(password);
    
                // email: kakao email
                String email = kakaoUserInfo.getEmail();
                // role: 일반 사용자
                UserRoleEnum role = UserRoleEnum.USER;
    
                kakaoUser = new User(nickname, encodedPassword, email, role, kakaoId);
                userRepository.save(kakaoUser);
            }
  • 強制登録処理
  • 「正常にログインしたユーザー情報」はSecurityContextに格納される
  • SecurityContextHolderから直接SecurityContextに「ログイン成功ユーザー情報」
  • を追加
  • 実施
  •       // 4. 강제 로그인 처리
          UserDetails userDetails = new UserDetailsImpl(kakaoUser);
          Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
          SecurityContextHolder.getContext().setAuthentication(authentication);
  • 以降機能別に再包装する場合は、簡単に使用できます.
  • KaoUserService、KaKaoUserInfoDtoなどを使用してファイル分離を行うこともできます.