Springframework에서 Naver API를 이용한
로그인 및 회원가입을 통한 정보 불러오기
웹사이트를 제작하다 보면 홈페이지 자체 회원가입도 존재하지만,
요즘에는 소셜을 이용한 로그인도 필수일 정도로 대부분의 사이트에서 구현되어 있는 기능이다.
지난번에는 Kakao API를 이용한 회원가입, 로그인 및 회원 정보를 가져오는 블로깅을 하였는데
이 중 네이버 API를 이용한 로그인 및 회원 정보를 가져올 수 있는 방법에 대해 알아볼 예정이다.
* API안의 내용이 많겠지만, 예시의 편의를 위해 이름(닉네임)과 이메일만 가져올 예정이다.
다른 정보를 가져오기 위한 방법은 이름과 이메일을 가져오는 방식과 동일하기 때문에 개인적으로 실습해 보기를 바란다!
[준비하기]
이번에도 네이버 개발자 선터를 통해 애플리케이션 등록은 먼저 해야 API를 사용할 수 있다.
1. 네이버 개발자 센터 접속하기
https://developers.naver.com/main/
NAVER Developers
네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음
developers.naver.com
2. 상단의 Application에서 애플리케이션 등록 선택
3. 애플리케이션 내용 입력 후 등록하기
- 사용 API에서 '네이버 로그인' 선택 시 나오는 정보 입력하기
- 애플리케이션을 어떤 환경(PC)에서 사용할지 선택 후 도메인 입력 후 저장
* Redirec URL은 로그인 후 돌아갈 URL을 지정하면 된다.
3. 등록 후 나오는 Client_ID와 Client_Secret 저장해 놓기
- 만약 API 등록 시 입력한 내용을 변경해야 하는 경우 여기서 변경할 수 있음
여기까지 등록했다면, 이제 이 API를 활용하여 회원가입 및 로그인을 구현할 수 있다.
전체적으로 API를 사용하는 방법은 Kakao API를 사용했던 방법과 다르지 않기 때문에
이를 이해하고 있다면 크게 어렵지 않을 것이다.
자세한 방법은 네이버 개발자센터에서 제공하는 API 명세서를 참고하면 된다.
https://developers.naver.com/docs/login/api/api.md
네이버 로그인 API 명세 - LOGIN
네이버 로그인 API 명세 네이버 로그인 API는 네이버 로그인 인증 요청 API, 접근 토큰 발급/갱신/삭제 요청API로 구성되어 있습니다. 네이버 로그인 인증 요청 API는 여러분의 웹 또는 앱에 네이버
developers.naver.com
[코드작성]
1. 네이버 로그인 인증 요청(인가 코드 요청)
- 네이버의 경우 로그인 인증 요청에 성공할 경우 Code를 발급해주고, 이를 이용해 토큰을 발급 받을 수 있다.
- Client_ID에는 위에서 애플리케이션 등록 시 받은 Client_ID를 사용하면 된다.
- 네이버의 경우에는 State를 함께 입력해 요청을 진행해야 하는데 해당 State는 네이버 로그인 인층 요청에 있는 예시의 State를 이용했다. (state = hLiDdL2uhPtsftcU)
[login.jsp]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<a href="https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=Client_ID&redirect_uri=http://localhost:8080/naverLogin&state=hLiDdL2uhPtsftcU
">
<img src="kakaoLogin.png"/>
</a>
</body>
</html>
인가 코드를 잘 받아왔는지는 Controller를 통해 확인해 볼 예정이며,
해당 Controller는 인가 코드 확인을 위한 코드로 추후 변경할 예정이다.
[NaverLoginController.java]
@Controller
public class NaverLoginController {
@GetMapping("/naverLogin")
@ResponseBody
public String naver(@RequestParam String code, @RequestParam String state){
System.out.println(code);
System.out.println(state);
return code;
}
}
(1) 네이버에 로그인 인증 요청
(2) 인가 코드 확인하기
- 동의 후 게속하기 버튼을 클릭하면 요청 시 보낸 Redirect_URL이 http://localhost:8080/kakaoLogin 였기 때문에 해당 (2)의 컨트롤러 매핑이 코드를 받게 된다.
@RequestParam을 이용해 code와 state를 가져오면 토큰 요청 준비가 끝난 것이다.
2. code, state를 이용한 토큰 요청
[KakaoLoginService.java]
@Service
public class NaverLoginService {
// 토큰 요청 메서드
public String token(String code, String state) throws Exception {
// (1)
String clientId = "/*Client_ID*/";
String clientSecret = "/*Client_Secret*/";
String redirectURI = URLEncoder.encode("http://localhost:8080/naverLogin", "UTF-8");
// (2) 토큰 요청을 위한 URL 생성
StringBuilder apiURL = new StringBuilder("https://nid.naver.com/oauth2.0/token?");
apiURL.append("grant_type=authorization_code&");
apiURL.append("client_id=").append(clientId);
apiURL.append("&client_secret=").append(clientSecret);
apiURL.append("&redirect_uri=").append(redirectURI);
apiURL.append("&code=").append(code);
apiURL.append("&state=").append(state);
// (3) 토큰 URL 접속
URL url = new URL(apiURL.toString());
HttpURLConnection con = (HttpURLConnection)url.openConnection();
// 메서드 지정
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader br;
System.out.print("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();
// (4) 토큰 응답 확인
System.out.println(res.toString());
// 에러 처리 진행
if(responseCode!=200) {
throw new Exception(res.toString());
}
String token = res.toString();
// (5) 토큰에서 필요한 토큰들만 가져오기
JSONParser parser = new JSONParser();
JSONObject tokenAll = (JSONObject) parser.parse(token); // 가져온 데이터를 json 형태로 파싱 진행
String access = (String) tokenAll .get("access_token");
return access;
}
}
(1) 애플리케이션 등록 후 받은 Client_ID와 Client_Secret을 입력
(2) 요청시 필요한 정보 설정
- 네이버 로그인의 경우 토큰 요청에 필요한 정보들을 파라미터에 넣어서 보내기 때문에 URL 설정 후 요청
(3) 토큰을 받기 위한 URL을 통해 접속하여 openConnection() 메서드를 이용해 HttpURLConnection의 인스턴스 생성
- URLConnection에 대한 설명은 아래를 참고하길 바람!
https://kcode-recording.tistory.com/319
[JAVA] URL을 통해 서버와 통신하는 URLConnection/HttpURLConnection
JAVA 애플리케이션과 URL 을 연결해주는 클래스 URLConnection과 HttpURLConnection URLConnection/HttpURLConnection 이란? URLConnection은 Java 애플리케이션과 URL을 연결해주는 수퍼 클래스로, 일반 URL에 대한 API를 제
kcode-recording.tistory.com
(4) 토큰에 대한 정보를 잘 받아왔는지 확인하기
(5) access 토큰 추출하기
- 해당 토큰 중 access_token만을 받아 요청 시 사용할 예정이므로 JSON을 파싱하여 access_token 정보만 가져오기
- JSON 파싱에 대한 정보를 아래 블로깅을 참고하기 바람
https://kcode-recording.tistory.com/325
[Spring] Spring Json 파싱해서 값 가져오기
JSON에서 원하는 값을 가져오기 위한 parsing 데이터를 요청하고 받아올 때 JSON 형태를 많이 이용하는데, JSON에서 자신이 원하는 값을 가져오기 위한 방법을 정리하고자 한다. JSON의 형태는 아래와 M
kcode-recording.tistory.com
3. 사용자 정보 받아오기
[KakaoLoginService.java]
// 사용자 정보 요청
public UserInfo info(String token) throws Exception {
// (1) 사용자 인증 요청
URL url = new URL("https://openapi.naver.com/v1/nid/me");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization","Bearer " + access);
BufferedReader br;
int resultCode = conn.getResponseCode();
System.out.println(resultCode);
if(resultCode>=200 && resultCode<+300){ // 정상인 경우
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}else{ //에러
br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder responseBuilder = new StringBuilder();
String line;
while((line=br.readLine()) != null){
responseBuilder.append(line);
}
br.close();
conn.disconnect();
// (2) 요청한 정보 확인
System.out.println(responseBuilder.toString());
// (3) 필요한 정보 파싱하기
JSONParser parsing = new JSONParser();
JSONObject info = (JSONObject) parsing.parse(responseBuilder.toString());
System.out.println(info.toJSONString());
JSONObject naverInfo = (JSONObject) info.get("response");
String email = (String)naverInfo.get("email");
String nickName = (String)naverInfo.get("name");
UserInfo userInfo = new UserInfo();
userInfo.setEmail(email);
userInfo.setNickName(nickName);
return userInfo;
}
(1) 사용자 기본 정보 요청하기
(2) 받아온 응답 확인하기
- 해당 응답은 기존에 사용자 동의 받은 정보만 가져올 수 있으며, 가져올 정보에 대한 선택은 네이버 개발자센터에서 수정 가능
(3) 이름과 이메일만 추출하기 위해 JSON 파싱하기
- JSON에 대한 파싱은 토큰에서 사용한 파싱 방법과 동일하며, 더 자세한 내용은 아래 블로깅을 참고하길 바란다.
- 추출한 정보는 리턴
- https://kcode-recording.tistory.com/325
[Spring] Spring Json 파싱해서 값 가져오기
JSON에서 원하는 값을 가져오기 위한 parsing 데이터를 요청하고 받아올 때 JSON 형태를 많이 이용하는데, JSON에서 자신이 원하는 값을 가져오기 위한 방법을 정리하고자 한다. JSON의 형태는 아래와 M
kcode-recording.tistory.com
[최종 코드]
* login.jsp는 처음 코드와 동일
[NaverController.java]
@Controller
public class NaverLoginController {
@GetMapping("/naverLogin")
public String naver(@RequestParam String code, @RequestParam String state, Model model){
try{
UserInfo userInfo = naverLoginService.naverLogin(code, state);
model.addAttribute("userInfo", userInfo);
session.setAttribute("user", userInfo);
return "naverCallback";
}catch (Exception e){
e.printStackTrace();
System.out.println(e.getMessage());
return e.getMessage();
}
}
}
[NaverLoginService.java]
@Service
public class NaverLoginService {
@Autowired
private UserDao userDao;
public UserInfo naverLogin(String code, String state) throws Exception{
String accessToken = token(code, state);
UserInfo loginInfo = info(accessToken); // api에서 가져온 회원 정보
UserInfo userInfo = userDao.selectUserByNaver(loginInfo.getEmail()); // DB에 존재 여부 확인
// 존재하지 않을 경우 디비에 insert 진행 및 userInfo에 대입
if(userInfo == null){
userDao.insertUserNaver(loginInfo);
userInfo = loginInfo;
}
return userInfo;
}
public String token(String code, String state) throws Exception {
String clientId = "WRDDsf6VYopAr3VsX_f5";
String clientSecret = "zkeCPJmyfa";
String redirectURI = URLEncoder.encode("http://localhost:8080/naverLogin", "UTF-8");
// 토큰 요청을 위한 URL 생성
StringBuilder apiURL = new StringBuilder("https://nid.naver.com/oauth2.0/token?");
apiURL.append("grant_type=authorization_code&");
apiURL.append("client_id=").append(clientId);
apiURL.append("&client_secret=").append(clientSecret);
apiURL.append("&redirect_uri=").append(redirectURI);
apiURL.append("&code=").append(code);
apiURL.append("&state=").append(state);
// 토큰 URL 접속
URL url = new URL(apiURL.toString());
HttpURLConnection con = (HttpURLConnection)url.openConnection();
// 메서드 지정
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader br;
System.out.print("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();
System.out.println(res.toString());
// 에러 처리 진행
if(responseCode!=200) {
throw new Exception(res.toString());
}
// 토큰에서 필요한 토큰들만 가져오기
JSONParser parser = new JSONParser();
JSONObject tokenAll = (JSONObject) parser.parse(token); // 가져온 데이터를 json 형태로 파싱 진행
String access = (String) tokenAll .get("access_token");
//String refresh_token = (String) tokenAll.get("refresh_token");
return access;
}
public UserInfo info(String token) throws Exception {
URL url = new URL("https://openapi.naver.com/v1/nid/me");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization","Bearer " + access);
BufferedReader br;
int resultCode = conn.getResponseCode();
System.out.println(resultCode);
if(resultCode>=200 && resultCode<+300){ // 정상인 경우
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}else{ //에러
br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder responseBuilder = new StringBuilder();
String line;
while((line=br.readLine()) != null){
responseBuilder.append(line);
}
br.close();
conn.disconnect();
System.out.println(responseBuilder.toString());
JSONParser parsing = new JSONParser();
JSONObject info = (JSONObject) parsing.parse(responseBuilder.toString());
System.out.println(info.toJSONString());
JSONObject naverInfo = (JSONObject) info.get("response");
String email = (String)naverInfo.get("email");
String nickName = (String)naverInfo.get("name");
UserInfo userInfo = new UserInfo();
userInfo.setEmail(email);
userInfo.setNickName(nickName);
return userInfo;
}
}
이 외에 필요한 기능도 네이버에서 제공하는 API를 참고하면 크게 어렵지 않을 것이다!
'공부 자료 > Spring' 카테고리의 다른 글
[Spring Boot] ResponseEntity란? (0) | 2023.11.20 |
---|---|
[MyBatis/Spring] About @Mapper/@Repository (0) | 2023.11.13 |
[Spring Boot] SpringBoot에서 JSP 사용하기 (0) | 2023.11.10 |
[Spring Boot] applicaiton.properties, application.yml 차이 (0) | 2023.11.10 |
[SpringBoot] SpringBoot에서 Mybatis/Database 사용을 위한 설정 (1) | 2023.11.10 |