[프로젝트 개선] - 웹사이트 제작 18. (Spring/Java) Oauth 카카오 로그인 연동(+ DB에 저장하기)

JINI·2023년 6월 22일
0
post-thumbnail

기본적인 웹사이트는 아이디/비밀번호를 입력해 로그인을 하지만 다른 방법으로 카카오나 구글 등으로 간단하게 로그인하기도 한다.
다양한 방법이 있지만 그 중에서 카카오 Login API를 연동해 보았다.

들어가기에 앞서...

☑️ Oauth란?

Open Authorization의 약자로 인증을 위한 프로토콜로 인터넷 사용자들이 비밀번호를 제공하지 않고, 웹사이트나 애플리케이션에 자신의 정보에 대한 접근권한을 부여할 수 있는 공통적인 수단으로 다른 웹사의트의 기능을 사용할 수 있게 해준다.


🗪 카카오 로그인 구현


☑️ 카카오 API 서비스 등록

☑️(1). 카카오 애플리케이션 등록

카카오 로그인 사용을 위해 카카오 개발자 페이지에서 내 애플리케이션을 추가한다.
이 내용은 저번에 다룬 적이 있으니 자세한 건 넘어간다!
REST API 앱키 를 얻고 웹 플랫폼 설정 등록 후 저장하면 된다.


☑️(2). 카카오 로그인 활성화

카카오 로그인 활성화 상태를 ON으로 변경한다.


☑️(3). Redirect URI 등록

Redirect URI는 인증에 필요한 code를 받고 발급된 code를 반환할 페이지이기 때문에 필수로 등록해야한다.


☑️(4). 동의항목 활성화

카카오 로그인시 필요한 동의항목을 선택한다.
내 경우는 프로젝트 목적이기 때문에 닉네임과 이메일만 가져오기로 했다.

동의 단계를 체크하고 동의 목적을 간단히 작성한 뒤 저장한다.
이메일은 필수 입력받으려면 검수가 필요하기 때문에 선택 동의로 체크했다.


이제 카카오 로그인을 이용할 수 있다.


☑️ 인가 코드 받기

요청 redirectURL로 카카오 로그인 동의 화면이 호출되고 사용자 동의 후 인가코드 발급을 요청하기 때문에 해당 프로젝트의 로그인 페이지에 코드를 작성한다.


📕JSP

kauth.kakao.com/oauth/authorize?client_id={REST API 키}&
redirect_uri={REDIRECT_URI}&response_type=code

RESTAPI_KEY는 발급된 값을 넣고, redirect_uri는 설정했던 uri로 하면 된다.

<a href=
"https://kauth.kakao.com/oauth/authorize?client_id=6cfbb25d1642a05ea21e31ecb13db43c&redirect_uri=http://localhost:8084/root/member/kakaoCallback&response_type=code"></a>

카카오 로그인하기를 클릭하면 사용자 동의화면이 뜬다.
동의하고 계속하기를 클릭하고 로그인 요청이 승인되면 등록한 Redirct URI로 토큰 받기 요청에 필요한 인가코드가 전송된다.


📕Controller

	@GetMapping("kakaoCallback")
	public String kakaoLogin(@RequestParam String code,HttpSession session)  throws IOException{
		System.out.println("코드 : " +code);
		String access_Token = kakao.getToken(code);
		kakaoMemberDTO userInfo = kakao.getKakaoUserInfo(access_Token);

		if (userInfo.getEmail() != null) {
			session.setAttribute("email", userInfo.getEmail());
			session.setAttribute("nickName", userInfo.getNickName());
			session.setAttribute("access_Token", access_Token);

			System.out.println("**access_Token : " + access_Token);
			System.out.println("**nickname : " + userInfo.getNickName());
			System.out.println("**email : " + userInfo.getEmail());
		}
		return "index";
	}

컨트롤러에서는 제대로 코드가 받아지는지 @RequestParam String code로 받아준다. 이메일과 닉네임 역시 확인해 주었다.

카카오 멤버 dto를 따로 만들어놓고 성공적으로 받아온 token이 service를 거쳐 로그인 성공시 카카오 유저 정보가 db에 저장이 되도록 한다.

db정보에 이메일이 null값이 아니라면 session에 가져온 이메일, 닉네임, 토큰을 저장하고 메인 페이지로 이동한다.


📕Service

token을 받아서 작업을 수행할 코드를 service에 작성한다.

☑️ 카카오 로그인 AccessToken 받기

@Service
public class kakaoLoginService implements kakaoService{
	@Autowired memberMapper memberMapper; //매퍼 연결하기

	//토큰값 받기위해 전송
	public String getToken (String authorize_code) {
		String access_Token = "";
		String refresh_Token = "";
		String reqURL = "https://kauth.kakao.com/oauth/token";

		try {
			URL url = new URL(reqURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();

			//POST 요청을 위해 기본값이 false인 setDoOutput을 true로 해야한다.
			conn.setRequestMethod("POST");
			conn.setDoOutput(true);

			//POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
			StringBuilder sb = new StringBuilder();
			sb.append("grant_type=authorization_code");
			sb.append("&client_id=6cfbb25d1642a05ea21e31ecb13db43c");  //본인이 발급받은 key
			sb.append("&redirect_uri=http://localhost:8084/root/member/kakaoCallback");     // 본인이 설정해 놓은 경로
			sb.append("&code=" + authorize_code);
			bw.write(sb.toString());
			bw.flush();

			//결과 코드가 200이라면 성공
			int responseCode = conn.getResponseCode();
			System.out.println("responseCode : " + responseCode);

			//요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
			BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = "";
			String result = "";

			while ((line = br.readLine()) != null) {
				result += line;
			}
			System.out.println("response body : " + result);

			JsonParser parser = new JsonParser();
			JsonElement element = parser.parse(result);

			access_Token = element.getAsJsonObject().get("access_token").getAsString();
			refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString();
			System.out.println("access_token : " + access_Token);
			System.out.println("refresh_token : " + refresh_Token);

			br.close();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return access_Token;
	}
}

☑️ 카카오 사용자 정보를 가져와서 DB에 저장하기

이제 받은 access token을 이용해 사용자 정보를 조회한 뒤 이메일, 닉넴임을 db에 저장한다.

	public kakaoMemberDTO getKakaoUserInfo (String access_Token){

		kakaoMemberDTO userInfo = new kakaoMemberDTO();
		String reqURL = "https://kapi.kakao.com/v2/user/me";
		try {
			URL url = new URL(reqURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");

			//    요청에 필요한 Header에 포함될 내용
			conn.setRequestProperty("Authorization", "Bearer " + access_Token);

			int responseCode = conn.getResponseCode();
			System.out.println("responseCode : " + responseCode);

			BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

			String line = "";
			String result = "";

			while ((line = br.readLine()) != null) {
				result += line;
			}
			System.out.println("response body : " + result);

			JsonParser parser = new JsonParser();
			JsonElement element = parser.parse(result);

			JsonObject properties = element.getAsJsonObject().get("properties").getAsJsonObject();
			JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();

			String nickname = properties.getAsJsonObject().get("nickname").getAsString();
			String email = kakao_account.getAsJsonObject().get("email").getAsString();

			userInfo.setNickName(nickname);
			userInfo.setEmail(email);

		} catch (IOException e) {
			e.printStackTrace();
		}
		kakaoMemberDTO result = memberMapper.findKakao(userInfo);
		System.out.println("저장값 : " + result);

		if(result ==null) {
			//result null 이면 정보가 저장 안되어있는거라서 저보를 저장.
			memberMapper.kakaoInsert(userInfo);
			//저장하기위해 repository 로 이동
			return memberMapper.findKakao(userInfo);
			// 정보 저장후 컨트롤러에 정보를 보냄
			//result 를 리턴으로 보내면 null 이 리턴되므로 위코드를 사용.
		}else {
			return result;
			//정보가 있으므로 result 를 리턴함
		}

	}

📕mapper

public void kakaoInsert(kakaoMemberDTO userInfo);
public  kakaoMemberDTO findKakao(kakaoMemberDTO userInfo);

📕Mapper.xml

<resultMap id="kakao" type="com.care.root.member.dto.kakaoMemberDTO">
	<id property="nickname" column="kakao_nickname" />
	<result property="email" column="kakao_email" />
</resultMap>

<insert id="kakaoInsert" parameterType="String">
	insert into
	kakao_member(kakao_nickname,kakao_email)
	values(#{nickname},#{email})
</insert>

<select id="findKakao" parameterType="String" resultType="com.care.root.member.dto.kakaoMemberDTO" resultMap="kakao">
	select 	* from kakao_member where kakao_nickname=#{nickname}
	and kakao_email=#{email}
</select>

카카오 사용자 정보를 db에 저장하고 이메일과 닉네임을 가져올 쿼리문을 작성한다.

로그인 성공시 성공코드가 200과 함께 token값과 이메일과 닉네임을 제대로 가지고 온 것을 확인할 수 있다.

db에도 제대로 저장되있다!!!!🙂

profile
꾸준히 성장하는 개발자

0개의 댓글