250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- 코드업
- 자바알고리즘
- 프로세스
- 자바의정석
- 개발자
- 소셜로그인구현
- 국비지원
- 스프링부트
- Codeup
- 혼공컴운
- db
- 데이터베이스
- Java
- 프로그래머
- 미라클모닝
- 자바스크립트
- 알고리즘
- 백엔드
- 리액트
- 자바
- 프로그래밍
- 국비지원코딩
- SpringBoot
- 개발자일기
- 코딩
- 자바개발자
- 운영체제
- React
- 백엔드개발자
- 프로그래머스
Archives
- Today
- Total
초코딩(chocoding)
[Project - Spring Boot] 소셜 로그인/API - 네이버 : 기본 초기 세팅 / 로그인 정보 db에 담기 / 로그인정보 session에 담기 / 로그아웃 구현 본문
Project
[Project - Spring Boot] 소셜 로그인/API - 네이버 : 기본 초기 세팅 / 로그인 정보 db에 담기 / 로그인정보 session에 담기 / 로그아웃 구현
sweetychocoding 2024. 1. 24. 14:54728x90
먼저 네이버 소셜 로그인 기초 세팅은 구글링하여 다른 블로그를 참고했다.
Spring Boot | OAuth 2 소셜 로그인 구현 (Naver)
네이버 소셜 로그인 구현하기
velog.io
.
.
.
나는 카카오, 네이버, 구글 이 세 개의 소셜 로그인을 구현할 예정인데
현재로는 카카오, 네이버만 구현한 상태이다.
처음 controller를 설계할 때 너무나도 무지해서 (.... ㅠㅠ)
카카오에서 넘어오는 값과 네이버에서 넘어오는 값을... 뭘로 구별해야 할까.. 하다가
모르겠어서 일단 controller를 따로따로 만들었다...
지금은 어느정도 .. (?) 감을 잡아서
구글 로그인 구현을 하기 전에 controller를 하나로 합칠 생각이다.
어쨌든.. 무ㅝ... 이런 말을 하는 이유는
지금은 컨트롤러가 소셜당 하나씩... 이닷...! 라는 말을 하고 싶었슴니다.. 으하하하하
그럼 고고링
...!!!
LoginController
package com.cm.personalProject.controller;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.cm.personalProject.entity.User;
import com.cm.personalProject.service.KakaoAPI;
import com.cm.personalProject.service.NaverAPI;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@AllArgsConstructor
@RequestMapping(value = "/social")
@Controller
public class LoginController {
private KakaoAPI kakao;
private NaverAPI naver;
@GetMapping("/loginPage")
public void getLoginPage() {
}
@GetMapping("/klogin")
public String klogin(@RequestParam("code") String code) {
System.out.println(code);
String access_token = kakao.getAccessToken(code);
System.out.println("controller access_token : " + access_token);
String userInfo;
try {
userInfo = kakao.getUserInfo(access_token);
if ("성공".equals(userInfo)) {
return "redirect:/home";
} else {
return "redirect:/social/loginPage";
}
} catch (IOException e) {
e.printStackTrace();
return "redirect:/social/loginPage";
}
}
@GetMapping("/nlogin")
public String nlogin(@RequestParam("code") String code, Model model, HttpSession session) {
System.out.println(code);
String access_token = naver.getAccessToken(code);
try {
User userInfo = naver.getUserInfo(access_token).orElse(null);
System.out.println("*****************" + userInfo);
if (userInfo != null) {
session.setAttribute("loginUser", userInfo);
return "redirect:/home";
} else {
return "redirect:/social/loginPage";
}
} catch (Exception e) {
return "redirect:/social/loginPage";
}
}
@GetMapping(value = "/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/home";
}
}
NaverAPI
package com.cm.personalProject.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Optional;
import org.springframework.stereotype.Service;
import com.cm.personalProject.domain.OauthId;
import com.cm.personalProject.entity.User;
import com.cm.personalProject.repository.UserRepository;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Service
@RequiredArgsConstructor
@Log4j2
public class NaverAPI {
private final UserRepository repository;
// Naver API로부터 인증 코드를 사용하여 액세스 토큰을 얻어오는 메서드
public String getAccessToken(String code) {
try {
String redirectURI = URLEncoder.encode("http://localhost:8080/social/nlogin", "UTF-8");
String apiURL = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&";
apiURL += "client_id=" + "****1lTRrhBHowHEvL4f";
apiURL += "&client_secret=" + "****6CNy4Z";
apiURL += "&redirect_uri=" + "http://localhost:8080/social/nlogin";
apiURL += "&code=" + code;
apiURL += "&state=" + 1234;
System.out.println("apiURL=" + apiURL);
URL url = new URL(apiURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader br;
if (responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
System.out.println("에러 응답: " + br.readLine()); // 에러 응답 출력
return null;
}
String inputLine;
StringBuffer res = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
res.append(inputLine);
}
if (responseCode == 200) {
System.out.println(res.toString());
}
String result = res.toString();
System.out.println("response body : " + result);
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
br.close();
return element.getAsJsonObject().get("access_token").getAsString();
} catch (Exception e) {
log.error("Error during getAccessToken", e);
return null;
}
}
// getUserInfo
public Optional<User> getUserInfo(String accessToken) throws IOException {
// 네이버 로그인 접근 토큰;
String apiURL = "https://openapi.naver.com/v1/nid/me";
String headerStr = "Bearer " + accessToken; // Bearer 다음에 공백 추가
String result = requestToServer(apiURL, headerStr);
System.out.println("사용자 정보 " + result);
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
JsonObject response = element.getAsJsonObject().get("response").getAsJsonObject();
System.out.println("*****response: " + response);
String token_id = response.getAsJsonObject().get("id").getAsString();
String nickname = response.getAsJsonObject().get("name").getAsString();
String email = response.getAsJsonObject().get("email").getAsString();
System.out.println("email" + email);
Optional<User> opt_user = repository.findById(new OauthId("naver", token_id));
System.out.println("--------opt_user : " + opt_user);
User user = new User();
if (opt_user.isPresent()) {
return opt_user;
} else {
user.setUseremail(email);
user.setUsername(nickname);
user.setOauthtype("naver");
user.setOauthtoken(token_id);
repository.save(user);
return Optional.of(user);
}
}
private String requestToServer(String apiURL, String headerStr) throws IOException {
URL url = new URL(apiURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
System.out.println("header Str: " + headerStr);
if (headerStr != null && !headerStr.equals("")) {
con.setRequestProperty("Authorization", headerStr);
}
int responseCode = con.getResponseCode();
BufferedReader br;
System.out.println("responseCode=" + responseCode);
if (responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}
String inputLine;
StringBuffer res = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
res.append(inputLine);
}
br.close();
if (responseCode == 200) {
return res.toString();
} else {
return null;
}
}
}
또한 로그인이 되었는지 확인이 되지 않아 테스트할 때 번거로워서
session에 로그인 유저 정보를 저장하고
로그아웃 기능을 구현하였다.
home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>메롱메롱 테스트</h2>
<c:if test="${not empty sessionScope.loginUser}">
${sessionScope.loginUser.username}님 안녕하세요.
<br />
<a href="social/logout">로그아웃</a>
<a>게시판가기</a>
</c:if>
<c:if test="${empty sessionScope.loginUser}">
<a href="social/loginPage">로그인</a>
</c:if>
<a>게시판가기</a>
</body>
</html>
.
.
.
사실 현재 코드 중복이 많아서 아쉬움이 많은 편이다.
일단 기능 구현에 초점을 두어서 코드 최적화 시키는 것을 뒤로 미뤘다.
다음 블로그 글에서는 중복을 없애고 최적화된 코드에 대해서 다뤄볼까 한다.
또한 구글 로그인 기능을 구현하기 전에
aws를 통하여 배포를 먼저 도전해보고 싶기 때문에
어떤 걸 먼저해야 될 지 고민을 해봐야 될 것 같다.
이상~
728x90