parent
1b55a58e39
commit
c6a3166183
@ -0,0 +1,24 @@
|
||||
package kr.xit.ens.support.nice.service;
|
||||
|
||||
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
|
||||
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
*
|
||||
* packageName : kr.xit.ens.support.nice.service
|
||||
* fileName : INiceCiService
|
||||
* author : limju
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface INiceCiService {
|
||||
TokenResponse generateToken(final TokenRequest reqDTO);
|
||||
TokenResponse revokeToken(final String token);
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package kr.xit.ens.support.nice.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses;
|
||||
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
|
||||
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
|
||||
import kr.xit.core.spring.util.ApiWebClientUtil;
|
||||
import kr.xit.core.support.utils.JsonUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.logging.log4j.util.Base64Util;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
*
|
||||
* packageName : kr.xit.ens.support.nice.service
|
||||
* fileName : NiceCiService
|
||||
* author : limju
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiService {
|
||||
@Value("${contract.nice.host}")
|
||||
private String HOST;
|
||||
@Value("${contract.nice.client-id}")
|
||||
private String CLIENT_ID;
|
||||
@Value("${contract.nice.client-secret}")
|
||||
private String CLIENT_SECRET;
|
||||
@Value("${contract.nice.api.generate-token}")
|
||||
private String API_GENERATE_TOKEN;
|
||||
@Value("${contract.nice.api.revoke-token}")
|
||||
private String API_REVOKE_TOKEN;
|
||||
@Value("${contract.nice.api.publickey}")
|
||||
private String API_PUBLICKEY;
|
||||
@Value("${contract.nice.api.symmetrickey}")
|
||||
private String API_SYMMETRICKEY;
|
||||
@Value("${contract.nice.api.ci}")
|
||||
private String API_CI;
|
||||
|
||||
private final ApiWebClientUtil webClient;
|
||||
|
||||
public TokenResponse generateToken(final TokenRequest reqDTO){
|
||||
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, JsonUtils.toJson(reqDTO), TokenResponse.class, getHeaderMap());
|
||||
}
|
||||
|
||||
public TokenResponse revokeToken(final String token){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
map.put(HttpHeaders.AUTHORIZATION, String.format("Basic %s", Base64Util.encode(String.format("%s:%s:%s", token, (new Date().getTime() / 1000), this.CLIENT_SECRET))));
|
||||
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, null, TokenResponse.class, getHeaderMap());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
private Map<String,String> getHeaderMap(){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
map.put(HttpHeaders.AUTHORIZATION, String.format("Basic %s", Base64Util.encode(String.format("%s:%s", this.CLIENT_ID, this.CLIENT_SECRET))));
|
||||
return map;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package kr.xit.ens.support.nice.web;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import kr.xit.biz.ens.model.kakao.KkopayDocDTO.ValidTokenRequest;
|
||||
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
|
||||
import kr.xit.core.model.ApiResponseDTO;
|
||||
import kr.xit.ens.support.nice.service.INiceCiService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
*
|
||||
* packageName : kr.xit.ens.support.nice.web
|
||||
* fileName : NiceCiController
|
||||
* author : limju
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Tag(name = "NiceCiController", description = "Nice CI API")
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/nice/v1")
|
||||
public class NiceCiController {
|
||||
private final INiceCiService service;
|
||||
|
||||
@Operation(summary = "기관용 토큰 발급 요청", description = "기관용 토큰 발급 요청")
|
||||
@PostMapping(value = "/generateToken", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponseDTO<?> generateToken(
|
||||
@RequestBody final TokenRequest reqDTO
|
||||
) {
|
||||
return ApiResponseDTO.success(service.generateToken(reqDTO));
|
||||
}
|
||||
|
||||
@Operation(summary = "기관용 토큰 폐기", description = "기관용 토큰 폐기")
|
||||
@PostMapping(value = "/revokeToken", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ApiResponseDTO<?> revokeToken(
|
||||
@RequestParam final String accessToken
|
||||
) {
|
||||
return ApiResponseDTO.success(service.revokeToken(accessToken));
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
package kr.xit.biz.ens.model.nice;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Digits;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import kr.xit.biz.common.ApiConstants;
|
||||
import kr.xit.core.model.IApiResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description : Nice CI DTO
|
||||
*
|
||||
* packageName : kr.xit.biz.ens.model.nice
|
||||
* fileName : NiceCiDTO
|
||||
* author : limju
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public class NiceCiDTO {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 기관용 Token(50년 유효) 발급 요청
|
||||
* url : /digital/niceid/oauth/oauth/token
|
||||
* content-type : application/x-www-form-urlencoded
|
||||
* Authorization : Basic + Base64Encoding(access_token:current_timestamp:client_id)
|
||||
* - access_token : 만료할 access_token
|
||||
* - client_id : access_token발급에 사용된 client_id
|
||||
* - current_timestamp
|
||||
* Date currentDate = new Date();
|
||||
* long current_timestamp = currentDate.getTime() /1000
|
||||
* </pre>
|
||||
*/
|
||||
@Schema(name = "Token", description = "기관용 Token(50년 유효) 발급 요청 파라메터 DTO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class TokenRequest {
|
||||
/**
|
||||
* default 로 고정
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED, title = "scope", example = "default")
|
||||
@NotBlank(message = "scope는 필수입니다")
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* clinet_credentials 로 고정
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED, title = "grant_type", example = "clinet_credentials")
|
||||
@NotBlank(message = "grant_type은 필수입니다")
|
||||
private String grant_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 기관용 Token(50년 유효) 발급 요청 응답
|
||||
* url : /digital/niceid/oauth/oauth/token
|
||||
* content-type : application/json
|
||||
* </pre>
|
||||
*/
|
||||
@Schema(name = "TokenResponse", description = "기관용 Token(50년 유효) 발급 요청 결과 DTO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class TokenResponse implements IApiResponse {
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED)
|
||||
private DataHeader dataHeader;
|
||||
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED)
|
||||
private DataBody dataBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 기관용 Token 폐기 응답
|
||||
* 요청
|
||||
* url : /digital/niceid/oauth/oauth/token/revokeById
|
||||
* Authorization : Basic + Base64Encoding(access_token:current_timestamp:client_id)
|
||||
* - access_token : 만료할 access_token
|
||||
* - client_id : access_token발급에 사용된 client_id
|
||||
* - current_timestamp
|
||||
* Date currentDate = new Date();
|
||||
* long current_timestamp = currentDate.getTime() /1000
|
||||
* </pre>
|
||||
*/
|
||||
@Schema(name = "TokenRevokeResponse", description = "기관용 Token 폐기 요청 결과 DTO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class TokenRevokeResponse implements IApiResponse {
|
||||
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED)
|
||||
private DataHeader dataHeader;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 기관용 토큰 발급 응답 dataHeader
|
||||
*/
|
||||
@Schema(name = "DataHeader", description = "TokenResponse dataHeader DTO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class DataHeader {
|
||||
/**
|
||||
* 응답코드
|
||||
* 정상 : 1200, 그외 오류
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED, title = "응답코드", example = "1200")
|
||||
@NotBlank
|
||||
private String GW_RSLT_CD;
|
||||
|
||||
/**
|
||||
* 응답메세지
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.REQUIRED, title = "응답메세지", example = "오류없음")
|
||||
@NotBlank
|
||||
private String GW_RSLT_MSG;
|
||||
|
||||
/**
|
||||
* TRAN_ID
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO, title = "TRAN_ID", example = "20230906120000")
|
||||
private String TRAN_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 기관용 토큰 발급 응답 dataHeader
|
||||
*/
|
||||
@Schema(name = "DataBody", description = "TokenResponse dataBody DTO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class DataBody {
|
||||
//-----------------------------------------------------------------------
|
||||
// 토근 발급 요청시 필수
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* 사용자 엑세스 토큰 값 : token 발급시 필수
|
||||
* 모든 API 요청시 헤더에 access_token을 포함하여 전송
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO, title = "사용자 엑세스 토큰 값", example = " ")
|
||||
@NotBlank
|
||||
private String access_token;
|
||||
|
||||
/**
|
||||
* token_type : token 발급시 필수
|
||||
* bearer로 고정
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO, title = "token_type", example = "bearer")
|
||||
@NotBlank
|
||||
private String token_type;
|
||||
|
||||
/**
|
||||
* access 토큰 만료 시간(초) : token 발급시 필수
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO, title = "access 토큰 만료 시간(초)", example = "1.57698305E9")
|
||||
@NotBlank
|
||||
private int expires_in;
|
||||
|
||||
/**
|
||||
* 요청한 scope 값 : token 발급시 필수
|
||||
* 기본 : default
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO, title = "요청한 scope 값", example = "default")
|
||||
@NotBlank
|
||||
private String scope;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// 토큰 폐기 요청시 필수
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* token 폐기시 필수
|
||||
* true or false
|
||||
*/
|
||||
@Schema(requiredMode = RequiredMode.AUTO)
|
||||
@NotBlank
|
||||
private boolean result;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package kr.xit.core.support.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import kr.xit.core.exception.BizRuntimeException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
*
|
||||
* packageName : kr.xit.core.support.utils
|
||||
* fileName : SecureUtils
|
||||
* author : limju
|
||||
* date : 2023-09-06
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2023-09-06 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public class SecureUtils {
|
||||
/**
|
||||
* sha256 암호화
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public static String hexSha256(String text) {
|
||||
StringBuffer sbuf = new StringBuffer();
|
||||
|
||||
try {
|
||||
MessageDigest mDigest = MessageDigest.getInstance("SHA-256");
|
||||
mDigest.update(text.getBytes());
|
||||
|
||||
byte[] msgStr = mDigest.digest();
|
||||
|
||||
for(int i = 0; i < msgStr.length; i++) {
|
||||
byte tmpStrByte = msgStr[i];
|
||||
String tmpEncTxt = Integer.toString((tmpStrByte & 0xff) + 0x100, 16).substring(1);
|
||||
|
||||
sbuf.append(tmpEncTxt);
|
||||
}
|
||||
} catch (NoSuchAlgorithmException nae){
|
||||
throw BizRuntimeException.create(nae.getMessage());
|
||||
}
|
||||
return sbuf.toString();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue