사용했던 곳 :  LOL API 호출

 

구조 : LOL API SERVER <-> JAVA <-> JAVASCRIPT

 

사용한 이유 : 데이터 호출 시, 오래걸리는 요청이 있음 (아래요청이 4만2천 라인 JSON 데이터)

데이터를 받기전에 코드가 실행되는 것을 방지

 

Promise
    resolve 에서 함수를 실행 후 리턴하면, 첫번쨰 then 에서 fulfill , 두번째 then 에서 fail 처리

 

let data = [
  "KR_6208998597",
  "KR_6205788623",
  "KR_6205771899",
  "KR_6205761572",
  "KR_6205760049",
  "KR_6205739603",
  "KR_6205722929",
  "KR_6205707540",
  "KR_6205672619",
  "KR_6202903236",
  "KR_6202839588",
  "KR_6202132677",
  "KR_6201732901",
  "KR_6199858746",
  "KR_6197747393",
  "KR_6196545900",
  "KR_6196408408",
  "KR_6194805433",
  "KR_6194800776",
  "KR_6194658337"
]

async function requestData(data){
    const response = await fetch('http://localhost:8011/match/matchId', {
    method: 'POST', // *GET, POST, PUT, DELETE 등
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });
return response.json();
  
}

Promise.resolve()
.then(() => {
    return requestData(data)
}).then(res => {
    console.log(res)
})

입력

 

결과

package com.onware.portal.holidayapitest.Controller;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Map;

@Slf4j
@RestController
@NoArgsConstructor
public class Controller {

    private WebClient webClient;
    private String BASE_URL;
    private String serviceKey;

    @Autowired
    Controller(WebClient webClient) {
        this.webClient = webClient;
    }

    @GetMapping("/getholiday")
    public ResponseEntity<String> getHoliday(@RequestParam Map<String, String> params) throws UnsupportedEncodingException, URISyntaxException {
        serviceKey = "인코딩된키"
        String solYear = params.get("solYear");
        String solMonth = params.get("solMonth");

        BASE_URL = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo";

        StringBuilder urlBuilder = new StringBuilder(BASE_URL);
        urlBuilder.append("?" + URLEncoder.encode("serviceKey", "UTF-8") + "="+ serviceKey);
        urlBuilder.append("&" + URLEncoder.encode("_type", "UTF-8") + "=" + URLEncoder.encode("json", "UTF-8"));
        urlBuilder.append("&" + URLEncoder.encode("solYear", "UTF-8") + "=" + URLEncoder.encode(solYear, "UTF-8"));
        urlBuilder.append("&" + URLEncoder.encode("solMonth", "UTF-8") + "=" + URLEncoder.encode(solMonth, "UTF-8"));

        log.info(urlBuilder.toString());

        Mono<String> request = webClient.get()
                .uri(URI.create(urlBuilder.toString()))
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(String.class);

        return new ResponseEntity<>(request.blockOptional().get(), HttpStatus.OK);
    }
}

Kakao Developers 페이지에서 가져온 내용

https://developers.kakao.com/docs/latest/ko/kakaologin/common

 

정리

1) 카카오 계정과 어플리케이션을 연결하고, 토큰을 발급 받아서 사용자를 해당 어플리케이션에 로그인 시킨다.

2) Access Token : 카카오 API 호출 권한 부여 토큰

   -> 로그인을 통해 발급

3) Refresh Token : Access Token 갱신

4) 해당 토큰으로 사용자정보를 얻은 다음 DB에 따로 가입처리를 해주어야함

 

인증 과정

 

정리

1) 인증서버에서 제공할 로그인 페이지 필요

2) 토큰을 생성 해주고 전달해주어야함

3) 구현해보려면, OAuth 2.0 서버의 사용자 DB / 어플리케이션 서버의 DB 이렇게 별도로 사용자 데이터베이스 필요

'API > OAuth2.0' 카테고리의 다른 글

OAuth 2.0 ?  (0) 2021.06.21

 

내 생각

 

   OAuth 2.0 서버를 만들어 보려는 이유는 인증서비스 제공이 어떻게 이루어지는지 이해해보려고 함이다.

요즘 없는 곳이 없는 카카오 소셜로그인 처럼 API 문서를 따라해보면, 나의 어플리케이션과 연동하는 것은 그리 어렵지않다.

 

하지만, 반대로 내가 인증서비스(OAuth 2.0) 서버를 구축하여, 서비스 제공자의 역할을 좀 더 자세히 알고 싶어서이다.

 


 

 

검색 해본 것

https://ko.wikipedia.org/wiki/OAuth

 

위키에서 OAuth를 검색해보니 관련 용어가 있어서 가져왔다.

 

  평소에 작업하면서 쓰는 용어는 인증 제공자로써 Service Provider 대신 IDP라고 쓰고, 위키에서 소비자라고 쓰는 부분은 어플리케이션 서비스 제공자로써 SP라고 쓰고 있어서 좀 헷갈리긴한다


OAuth에 관련된 용어들을 간략히 설명한다.

  • 사용자(user): 서비스 제공자와 소비자를 사용하는 계정을 가지고 있는 개인 -> 카카오계정 이용자
  • 소비자(consumer): Open API를 이용하여 개발된 OAuth를 사용하여 서비스 제공자에게 접근하는 웹사이트 또는 애플리케이션 -> 소셜로그인 연동을 하려고하는 개발자가 관리하는 웹사이트 또는 어플
  • 서비스 제공자(service provider): OAuth를 통해 접근을 지원하는 웹 애플리케이션(Open API를 제공하는 서비스)    -> 카카오 
  • 소비자 비밀번호(consumer secret) : 서비스 제공자에서 소비자가 자신임을 인증하기 위한 키 -> 내가 카카오와 서비스를 연동했다라는 인증키
  • 요청 토큰(request token) : 소비자가 사용자에게 접근권한을 인증받기 위해 필요한 정보가 담겨있으며 후에 접근 토큰으로 변환된다. -> 내 어플리케이션은 너희 카카오 인증서비스와 연결이 되있으니, 이 사용자가 카카오로그인을 성공하고나면 그 응답으로 인증받았다는 증거를 달라
  • 접근 토큰(access token) : 인증 후에 사용자가 서비스 제공자가 아닌 소비자를 통해서 보호된 자원에 접근하기 위한 키를 포함한 값.

 

정리

서비스 개발자가 카카오 인증과 연동을 해놓으면, 사용자는 카카오계정을 통해 로그인이 가능해진다.

로그인을 하면, 카카오 인증서버는 응답으로 토큰을 발행하고, 그 토큰으로 사용자가 인증을 받았다고 간주하고, 자신의 서비스에 로그인을 시킨다. 이 사용자에 대한 권한 관리는 별도로 어플리케이션에서 해주겠지만 인증주체가 외부에 있다는 것이 특징인것 같다.

 

 

 

'API > OAuth2.0' 카테고리의 다른 글

OAuth 2.0 인증 과정  (0) 2021.06.21

json방식으로 조회

package textbook.naverAPI;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class NaverSearchAPI {
		
    public String Search(String word) {
        String clientId = "your client code";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "your client secret code";//애플리케이션 클라이언트 시크릿값";
        StringBuffer response = null;
        try {
            String text = URLEncoder.encode(word, "UTF-8");
            String apiURL = "https://openapi.naver.com/v1/search/book.json?query="+ text; // json 결과
//            String apiURL = "https://openapi.naver.com/v1/search/book.xml?query="+ text; // xml 결과
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setRequestMethod("GET");
            con.setRequestProperty("X-Naver-Client-Id", clientId);
            con.setRequestProperty("X-Naver-Client-Secret", clientSecret);
            int responseCode = con.getResponseCode();
            BufferedReader br;
            if(responseCode==200) { // 정상 호출
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {  // 에러 발생
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }
            String inputLine;
            response = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                response.append(inputLine);
            }
            br.close();
            
        } catch (Exception e) {
            System.out.println(e);
        }
        return response.toString();
    }
}

ajax로 컨트롤러를 요청하고 / json으로 데이터를 받아서 처리하는 방법

function bookSearch(page) {
	var url = "bookSearch.text";
	var word = $("#word").val();/* 네이버 책 검색 */
	var listArr = null;
	var data = {
		word : word,
	}

	$.ajax({
		type : "post",
		url : url,
		data : data,
		dataType : "json",
		success : function(getData) {
			console.log(getData);
			console.log(getData.total);
			var total = getData.total;
			var start = getData.start;
			var display = getData.display;
			/* 페이지= index+1 */
			$(".find").html(total);
			listArr = new Array();
			for (var i = 0; i < display; i++) {
				listArr.push(getData.items[i]);
				console.log(listArr[i].title);
			}
			var i = page-1;
			$(".title ~ p").remove();
			$(".title").after("<p>" + listArr[i].title + "</p>");
			/*문자열 태그 제거필요*/
			var titleEncode = encodeURIComponent(listArr[i].title);
			$("#book_title").val(titleEncode);
			
			
			$(".link ~ p").remove();
			$(".link").after("<p>" + listArr[i].link + "</p>");
			var linkEncode = encodeURIComponent(listArr[i].link);
			$("#book_link").val(linkEncode);
			
			
			$(".image ~ p").remove();
			$(".image").after("<p>" + listArr[i].image + "</p>");
			var imgEncode = encodeURIComponent(listArr[i].image);
			$("#book_image").val(imgEncode);
			
			$(".author ~ p").remove();
			$(".author").after("<p>" + listArr[i].author + "</p>");
			$("#book_author").val(listArr[i].author);
			
			$(".price ~ p").remove();
			$(".price").after("<p>" + listArr[i].price + "</p>");
			$("#book_price").val(listArr[i].price);
			
			$(".discount ~ p").remove();
			$(".discount").after("<p>" + listArr[i].discount + "</p>");
			$("#book_discount").val(listArr[i].discount);
			
			$(".publisher ~ p").remove();
			$(".publisher").after("<p>" + listArr[i].publisher + "</p>");
			$("#book_publisher").val(listArr[i].publisher);
			
			$(".pubdate ~ p").remove();
			$(".pubdate").after("<p>" + listArr[i].pubdate + "</p>");
			$("#book_pubdate").val(listArr[i].pubdate);
			
			$(".isbn ~ p").remove();
			$(".isbn").after("<p>" + listArr[i].isbn + "</p>");
			$("#book_isbn").val(listArr[i].isbn);
			
			$(".description ~ p").remove();
			$(".description").after("<p>" + listArr[i].description + "</p>");
			
			var encode = encodeURIComponent(listArr[i].description);
			var decode = decodeURIComponent(listArr[i].description);
			console.log(encode);
			console.log(decode);
			$("#book_description").val(encode);
			
		},
		error : function(request, status, error) {
			alert("code = " + request.status + " message = "
					+ request.responseText + " error = " + error);
			console.log(error);
		}
	});
};

 

컨트롤러에서 처리방법

 

받은 데이터는 json방식이기때문에 jsonparse API 사용해서 파싱한다음 되돌려줌.

NaverSearchAPI search = new NaverSearchAPI();
				String word = request.getParameter("word");
				String result = search.Search(word);

				JSONParser paser = new JSONParser();
				Object obj = paser.parse(result);
				JSONObject jsonObj = (JSONObject) obj;
//				bookdetail.text  jsp페이지에서 -> ${requestScope.result.items}
				request.setAttribute("result", jsonObj);

				System.out.println("get" + result);
				PrintWriter out = response.getWriter();
				out.print(jsonObj);

 

Ajax->controller->jsonparsing->return Ajax->success 파라미터로 값이 넘어오고 받아서 처리