api token 소스정리
This commit is contained in:
Binary file not shown.
@@ -8,9 +8,7 @@ import net.jwsi.jcms.vpp.station.StationDto;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -19,62 +17,39 @@ import java.util.Map;
|
||||
@RequiredArgsConstructor
|
||||
public class ApiClient {
|
||||
|
||||
private final RestClient restClient;
|
||||
private final RestClient externalApiClient;
|
||||
|
||||
public ApiResponse<List<StationDto>> fetchStations(String baseUrl, String token) {
|
||||
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
|
||||
.path("/api/st/list")
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
return restClient.post()
|
||||
.uri(uri)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
public ApiResponse<List<StationDto>> fetchStations() {
|
||||
return externalApiClient.post()
|
||||
.uri("/api/st/list")
|
||||
.body(Collections.emptyMap())
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<ApiResponse<List<StationDto>>>() {});
|
||||
}
|
||||
|
||||
public ApiResponse<List<ProviderDto>> fetchProviders(String baseUrl, String token) {
|
||||
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
|
||||
.path("/api/provider/list")
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
return restClient.get()
|
||||
.uri(uri)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
public ApiResponse<List<ProviderDto>> fetchProviders() {
|
||||
return externalApiClient.get()
|
||||
.uri("/api/provider/list")
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<ApiResponse<List<ProviderDto>>>() {});
|
||||
}
|
||||
|
||||
public ApiResponse<List<ChgrResponseDto>> fetchChgr(String baseUrl, String token) {
|
||||
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
|
||||
.path("/api/charger/list")
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
return restClient.post()
|
||||
.uri(uri)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
public ApiResponse<List<ChgrResponseDto>> fetchChgr() {
|
||||
return externalApiClient.post()
|
||||
.uri("/api/charger/list")
|
||||
.body(Collections.emptyMap())
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<ApiResponse<List<ChgrResponseDto>>>() {});
|
||||
}
|
||||
public ApiResponse<List<ChgrHistResponseDto>> fetchChgrHist(String baseUrl, String token) {
|
||||
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
|
||||
.path("/api/charge/hist")
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
public ApiResponse<List<ChgrHistResponseDto>> fetchChgrHist(String startDt, String pageSize) {
|
||||
Map<String, String> requestBody = Map.of(
|
||||
"startDt", "2026-07-29",
|
||||
"pageSize","50"
|
||||
"startDt", startDt,
|
||||
"pageSize", pageSize
|
||||
);
|
||||
|
||||
return restClient.post()
|
||||
.uri(uri)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
return externalApiClient.post()
|
||||
.uri("/api/charge/hist")
|
||||
.body(requestBody)
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<ApiResponse<List<ChgrHistResponseDto>>>() {});
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.jwsi.jcms.vpp.api;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
public class ApiToken {
|
||||
private String jwt;
|
||||
private List<String> roles;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package net.jwsi.jcms.vpp.api;
|
||||
|
||||
import net.jwsi.jcms.vpp.utils.JwtUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class ExternalApiService {
|
||||
|
||||
private final RestClient authRestClient = RestClient.create();
|
||||
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${jcms.api.user-id}")
|
||||
private String apiUserId;
|
||||
|
||||
@Value("${jcms.api.user-pwd}")
|
||||
private String apiUserPwd;
|
||||
|
||||
private String cachedToken;
|
||||
private LocalDateTime tokenExpiryTime;
|
||||
|
||||
public synchronized String getAccessToken() {
|
||||
if (cachedToken != null && tokenExpiryTime != null && LocalDateTime.now().plusMinutes(1).isBefore(tokenExpiryTime)) {
|
||||
return cachedToken;
|
||||
}
|
||||
|
||||
URI uri = UriComponentsBuilder.fromUriString(baseUrl)
|
||||
.path("/api/auth/token")
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
Map<String, String> requestBody = Map.of(
|
||||
"userId", apiUserId,
|
||||
"pwd", apiUserPwd
|
||||
);
|
||||
|
||||
ApiResponse<ApiToken> response = authRestClient.post()
|
||||
.uri(uri)
|
||||
.body(requestBody)
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<ApiResponse<ApiToken>>() {});
|
||||
|
||||
if (response != null && response.getData() != null) {
|
||||
ApiToken tokenDto = response.getData();
|
||||
this.cachedToken = tokenDto.getJwt();
|
||||
this.tokenExpiryTime = JwtUtil.getExpirationTime(this.cachedToken);
|
||||
|
||||
return this.cachedToken;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("외부 API 토큰 발급에 실패했습니다.");
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,25 @@
|
||||
package net.jwsi.jcms.vpp.api;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@Configuration
|
||||
public class RestClientConfig {
|
||||
|
||||
@Bean
|
||||
public RestClient restClient() {
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setConnectTimeout((int) Duration.ofSeconds(5).toMillis());
|
||||
factory.setReadTimeout((int) Duration.ofSeconds(30).toMillis());
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Bean
|
||||
public RestClient externalApiClient(ExternalApiService externalApiService) {
|
||||
return RestClient.builder()
|
||||
.requestFactory(factory)
|
||||
.baseUrl(baseUrl)
|
||||
.requestInterceptor((request, body, execution) -> {
|
||||
String token = externalApiService.getAccessToken();
|
||||
request.getHeaders().set("Authorization", "Bearer " + token);
|
||||
return execution.execute(request, body);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import net.jwsi.jcms.utils.HttpUtil;
|
||||
import net.jwsi.jcms.utils.LoginUtil;
|
||||
import net.jwsi.jcms.vpp.api.ApiClient;
|
||||
import net.jwsi.jcms.vpp.api.ApiResponse;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@@ -22,11 +21,6 @@ import java.util.stream.Collectors;
|
||||
public class ChgrService extends BaseService<Chgr,String,ChgrRepository> {
|
||||
|
||||
private final ApiClient apiClient;
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${jcms.api.token}")
|
||||
private String apiToken;
|
||||
public ChgrService(ChgrRepository repository, ApiClient apiClient) {
|
||||
super(repository);
|
||||
this.apiClient = apiClient;
|
||||
@@ -34,7 +28,7 @@ public class ChgrService extends BaseService<Chgr,String,ChgrRepository> {
|
||||
@Transactional
|
||||
@Scheduled(cron = "0 0 0 * * *")
|
||||
public void getCharger() {
|
||||
ApiResponse<List<ChgrResponseDto>> response = apiClient.fetchChgr(baseUrl, apiToken);
|
||||
ApiResponse<List<ChgrResponseDto>> response = apiClient.fetchChgr();
|
||||
|
||||
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
|
||||
String msg = (response != null) ? response.getMessage() : "응답 없음";
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ChgrHist extends BaseStEntity {
|
||||
@Column(name = "RECHG_TIME")
|
||||
private String rechgTime; // 충전시간
|
||||
|
||||
@Column(name = "RECH_GWH")
|
||||
@Column(name = "RECHG_WH")
|
||||
private Integer rechGwh; // 충전량
|
||||
|
||||
@Column(name = "RECHG_AMT")
|
||||
|
||||
@@ -8,12 +8,12 @@ import net.jwsi.jcms.utils.HttpUtil;
|
||||
import net.jwsi.jcms.utils.LoginUtil;
|
||||
import net.jwsi.jcms.vpp.api.ApiClient;
|
||||
import net.jwsi.jcms.vpp.api.ApiResponse;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,11 +23,6 @@ public class ChgrHistService extends BaseService<ChgrHist, Integer, ChgrHistRepo
|
||||
|
||||
|
||||
private final ApiClient apiClient;
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${jcms.api.token}")
|
||||
private String apiToken;
|
||||
|
||||
public ChgrHistService(ChgrHistRepository repository, ApiClient apiClient) {
|
||||
super(repository);
|
||||
@@ -37,7 +32,8 @@ public class ChgrHistService extends BaseService<ChgrHist, Integer, ChgrHistRepo
|
||||
@Transactional
|
||||
@Scheduled(cron = "0 */10 * * * *")
|
||||
public void getChgrHist() throws IllegalAccessException {
|
||||
ApiResponse<List<ChgrHistResponseDto>> response = apiClient.fetchChgrHist(baseUrl, apiToken);
|
||||
|
||||
ApiResponse<List<ChgrHistResponseDto>> response = apiClient.fetchChgrHist(LocalDateTime.now().toString(), "50");
|
||||
|
||||
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
|
||||
String msg = (response != null) ? response.getMessage() : "응답 없음";
|
||||
|
||||
@@ -8,15 +8,11 @@ import net.jwsi.jcms.utils.HttpUtil;
|
||||
import net.jwsi.jcms.utils.LoginUtil;
|
||||
import net.jwsi.jcms.vpp.api.ApiClient;
|
||||
import net.jwsi.jcms.vpp.api.ApiResponse;
|
||||
import net.jwsi.jcms.vpp.station.Station;
|
||||
import net.jwsi.jcms.vpp.station.StationDto;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -26,12 +22,6 @@ public class ProviderService extends BaseService<Provider, String, ProviderRepos
|
||||
|
||||
private final ApiClient apiClient;
|
||||
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${jcms.api.token}")
|
||||
private String apiToken;
|
||||
|
||||
public ProviderService(ProviderRepository repository, ApiClient apiClient) {
|
||||
super(repository);
|
||||
this.apiClient = apiClient;
|
||||
@@ -40,7 +30,7 @@ public class ProviderService extends BaseService<Provider, String, ProviderRepos
|
||||
@Transactional
|
||||
@Scheduled(cron = "0 0 0 * * *")
|
||||
public void getProviders() {
|
||||
ApiResponse<List<ProviderDto>> response = apiClient.fetchProviders(baseUrl, apiToken);
|
||||
ApiResponse<List<ProviderDto>> response = apiClient.fetchProviders();
|
||||
|
||||
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
|
||||
String msg = (response != null) ? response.getMessage() : "응답 없음";
|
||||
|
||||
@@ -6,15 +6,13 @@ import net.jwsi.jcms.base.BaseService;
|
||||
import net.jwsi.jcms.base.EnumSqlType;
|
||||
import net.jwsi.jcms.utils.HttpUtil;
|
||||
import net.jwsi.jcms.utils.LoginUtil;
|
||||
import net.jwsi.jcms.vpp.api.ApiResponse;
|
||||
import net.jwsi.jcms.vpp.api.ApiClient;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import net.jwsi.jcms.vpp.api.ApiResponse;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -23,11 +21,7 @@ import java.util.stream.Collectors;
|
||||
public class StationService extends BaseService<Station,String,StationRepository> {
|
||||
|
||||
private final ApiClient apiClient;
|
||||
@Value("${jcms.api.base-url}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${jcms.api.token}")
|
||||
private String apiToken;
|
||||
public StationService(StationRepository repository, ApiClient apiClient) {
|
||||
super(repository);
|
||||
this.apiClient = apiClient;
|
||||
@@ -36,7 +30,7 @@ public class StationService extends BaseService<Station,String,StationRepository
|
||||
@Transactional
|
||||
@Scheduled(cron = "0 0 0 * * *")
|
||||
public void getStations() {
|
||||
ApiResponse<List<StationDto>> response = apiClient.fetchStations(baseUrl, apiToken);
|
||||
ApiResponse<List<StationDto>> response = apiClient.fetchStations();
|
||||
|
||||
if (response == null || !Integer.valueOf(200).equals(response.getCode())) {
|
||||
String msg = (response != null) ? response.getMessage() : "응답 없음";
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package net.jwsi.jcms.vpp.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Base64;
|
||||
|
||||
public class JwtUtil {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
public static LocalDateTime getExpirationTime(String jwtToken) {
|
||||
try {
|
||||
String[] parts = jwtToken.split("\\.");
|
||||
if (parts.length < 2) {
|
||||
throw new IllegalArgumentException("올바르지 않은 JWT 토큰 형식입니다.");
|
||||
}
|
||||
|
||||
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
|
||||
|
||||
JsonNode payloadNode = objectMapper.readTree(payloadJson);
|
||||
if (!payloadNode.has("exp")) {
|
||||
throw new IllegalStateException("토큰에 exp(만료시간) 필드가 존재하지 않습니다.");
|
||||
}
|
||||
|
||||
long expSeconds = payloadNode.get("exp").asLong();
|
||||
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochSecond(expSeconds), ZoneId.systemDefault());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("토큰 만료 시간 추출 실패", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,12 @@ jcms:
|
||||
manager-path: cms
|
||||
attr:
|
||||
main-url: /cms/main
|
||||
new-user-st: 9 # 1: ??, 9:????
|
||||
new-user-st: 9
|
||||
cms-name: VPP
|
||||
cms-title: VPP
|
||||
cms-bg-color: '#499'
|
||||
cms-image-url: /public/images/logo_jcms3.png
|
||||
copyright: Copyright 2026 ??????????? Inc.
|
||||
copyright: Copyright 2026 주식회사 진우시스템 Inc.
|
||||
authenticated-patten: /cms/**, /system/**, /api/**
|
||||
pass-url: /cms/main
|
||||
public-url: ''
|
||||
@@ -33,4 +33,5 @@ jcms:
|
||||
days: 30
|
||||
api:
|
||||
base-url: ${API_BASE_URL:http://dev.jinwoosi.co.kr:8072}
|
||||
token: ${API_TOKEN}
|
||||
user-id: ${API_USER_ID:apiuser}
|
||||
user-pwd: ${API_USER_PWD:apiuser}
|
||||
Reference in New Issue
Block a user