feat: mens-admin project 추가

dev
gitea-관리자 12 months ago
parent 82408afd53
commit f9d0f67175

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

@ -0,0 +1,174 @@
### API 가이드
[카카오페이 문서발송 단건](./document/카카오페이내문서함_1.문서발송(단건).pdf)
[카카오페이 문서발송 대량](./document/카카오페이내문서함_1.문서발송(대량).pdf)
[카카오페이 문서발송 네트워크가이드](./document/카카오페이내문서함_1.네트워크가이드.pdf)
### swagger
[API URL](http://localhost:8081/swagger-ui.html)
[Front URL](http://localhost:8080/swagger-ui.html)
[Front test page](http://localhost:8080/api/kakaopay/test)
### API 결과 수신
* 정상 수신
```java
public class ApiResponseDTO<T> implements Serializable {
private static final String FAIL_STATUS = "fail";
private static final String ERROR_STATUS = "error";
@Schema(example = "true", description = "에러인 경우 false", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean success;
@Schema(example = " ", description = "HttpStatus.OK", requiredMode = Schema.RequiredMode.REQUIRED)
private String code;
@Schema(description = "결과 데이타, 오류시 null", example = " ")
private T data;
@Schema(description = "오류 발생시 오류 메세지", example = " ", requiredMode = Schema.RequiredMode.AUTO)
@Setter
private String message;
@Schema(example = " ", description = "HttpStatus.OK", requiredMode = Schema.RequiredMode.AUTO)
private HttpStatus httpStatus;
@Schema(description = "API 실행 결과 데이타 수")
private int count;
}
```
* 정상 수신
```json
{
"success": true,
"code": "200",
"httpStatus": "OK",
"message": "성공했습니다.",
"data": {
"token_status": "USED",
"token_expires_at": 1624344762,
"token_used_at": 0,
"doc_box_sent_at": 0,
"doc_box_received_at": 0,
"authenticated_at": 0,
"user_notified_at": 0,
"payload": "payload 파라미터 입니다.",
"signed_at": 0
},
"count": 1,
"paginationInfo": null
}
```
* 에러 수신
```json
{
"success": false,
"code": "error",
"data": null,
"message": "로그인 정보가 올바르지 않습니다.",
"httpStatus": "BAD_REQUEST",
"count": 0,
"paginationInfo": null
}
```
* API 호출 결과가 서버등(네트웍장애)의 장애인 경우를 제외 하고
예외로 return 되는 경우는 없다(발생시 공통팀에 반드시 알려 줄 것)
```js
$.ajax({
url: url,
type: method,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(data),
beforeSend: (xhr) => {
//xhr.setRequestHeader(header, token);
$("#loading").show();
},
success: function (res, textStatus) {
console.log( JSON.stringify(res));
if(res.success){
//정상 응답
$("#resData").text(res.data)
}else{
//에러 응답
$("#errData").text(JSON.stringify(res));
}
},
error : function(data) {
// 여기로 오는 경우 공통팀에 알려 주세요
alert("점검필요-error로 return", data.responseText);
},
complete: () => {
$("#loading").hide();
}
});
```
### API(Restful call) validation
* Controller 단에서 @Validated 사용으로 처리 가능
* But, 이경우 API 로그를 남기기 위해 Service 단에서 체크 하도록 컨트롤러 단에서는 유효성 체크 skip
### spring validation
```text
@Valid는 Java, @Validated는 Spring에서 지원하는 어노테이션
@Validated@Valid의 기능을 포함하고, 유효성을 검토할 그룹을 지정할 수 있는 기능이 추가됨
```
```java
@Null // null만 혀용
@NotNull // null을 허용하지 않습니다. "", " "는 허용
@NotEmpty // null, ""을 허용하지 않습니다. " "는 허용
@NotBlank // null, "", " " 모두 허용하지 않습니다.
@Email // 이메일 형식을 검사합니다. 다만 ""의 경우를 통과 시킵니다
@Pattern(regexp = ) // 정규식을 검사할 때 사용됩니다.
@Size(min=, max=) // 길이를 제한할 때 사용됩니다.
@Max(value = ) // value 이하의 값을 받을 때 사용됩니다.
@Min(value = ) // value 이상의 값을 받을 때 사용됩니다.
@Positive // 값을 양수로 제한합니다.
@PositiveOrZero // 값을 양수와 0만 가능하도록 제한합니다.
@Negative // 값을 음수로 제한합니다.
@NegativeOrZero // 값을 음수와 0만 가능하도록 제한합니다.
@Future // 현재보다 미래
@Past // 현재보다 과거
@AssertFalse // false 여부, null은 체크하지 않습니다.
@AssertTrue // true 여부, null은 체크하지 않습니다.
```
### intellij devtools 활성
```text
1. IntelliJ - Preferencs…
2. 컴파일러 - build project automatically(프로젝트 자동 빌드) 체크
3. Advanced Settings > Compiler
Allow auto-make to start even if developed application is current running
(개발된 애플리케이션이 현재 실행 중인 경우에도 auto-make가 시작되도록 허용) 체크
# 1 ~ 3항 까지 설정후 에도 안되는 경우만 4번 설정
4. 서버설정 : Edit Configurations...
Modfy Options > On Update Action > Update Resources
```
### ens-api 배포 및 run : profile에 따라 local|dev|prod
```shell
# jdk : azul-17.0.1
# 프로젝트 root 폴더로 이동 : ens-parent
# 패키지 생성 : local|dev|prod
$ mvnw clean package -P local
# 실행 : 프로젝트폴더/ens-parent/ens-api/target에 생성된 jar파일 실행
$ c:\tools\java\azul-17.0.1\java -jar -Dspring.profiles.active=local .\mens-api.jar
# mvn 명령어 설명
# -pl [모듈명] : 모듈명의 프로젝트만 빌드
# -am : 의존성 있는 프로젝트 함께 빌드 - C가 A를 디펜던시로 가지고 있으며 C를 빌드하면 A -> C 순으로 빌드
$ mvnw clean package -pl mens-api -am -P local
# -amd : 의존성 있는 타 프로젝트 빌드 - C가 A를 디펜던시로 가지고 있는 경우 A를 빌드 하면 A -> C 순으로 빌드
$ mvnw clean package -pl mens-core -amd -P local
mvn clean package -pl mens-batch -am -P prod
```
### 스프링 배치 DB schema
[mysql DDL 스크립트](./document/batch-schema-mysql.sql)

Binary file not shown.

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>kr.xit</groupId>
<artifactId>mens-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>mens-admin</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>mens-admin</name>
<description>Mobile Electronic Administrator Web</description>
<dependencies>
<dependency>
<groupId>kr.xit</groupId>
<artifactId>mens-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
<scope>system</scope>
<systemPath>${basedir}/lib/ojdbc6.jar</systemPath>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*</include>
<include>static/**/*</include>
<include>egovframework/**/*</include>
<include>config/application.yml</include>
<include>config/application-app.yml</include>
<include>config/application-ens*</include>
<include>config/application-jpa.yml</include>
<include>config/application-${env}.yml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<!-- dependency 추가 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- dependency jar 파일명 -->
<!--finalName>${project.name}-${project.version}</finalName-->
<!-- 기본생성 jar와 dependency jar 가 포함된 각각 파일 생성-->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- spring-boot-maven-plugin : multi 프로젝트 이므로 mainClass 지정 필요 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<mainClass>kr.xit.EnsAdminApplication</mainClass>
<!-- 외부jar import -->
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,53 @@
package egovframework.com.jwt;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.support.utils.JsonUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
/**
* fileName : JwtAuthenticationEntryPoint
* author : crlee
* date : 2023/06/11
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/06/11 crlee
*/
//@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
// ResultVO resultVO = new ResultVO();
// resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
// resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
// ObjectMapper mapper = new ObjectMapper();
//
// //Convert object to JSON string
// String jsonInString = mapper.writeValueAsString(resultVO);
// 403 에러
@SuppressWarnings("rawtypes")
ApiResponseDTO apiResponseDTO = ApiResponseDTO.builder()
.success(false)
.code(String.valueOf(HttpStatus.FORBIDDEN.value()))
.message("인가된 사용자가 아닙니다")
.build();
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(MediaType.APPLICATION_JSON.toString());
response.setCharacterEncoding("UTF-8");
response.getWriter().println(JsonUtils.toJson(apiResponseDTO));
}
}

@ -0,0 +1,89 @@
package egovframework.com.jwt;
import egovframework.com.cmm.LoginVO;
import egovframework.com.cmm.util.EgovStringUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.xit.core.support.utils.Checks;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* fileName : JwtAuthenticationFilter
* author : crlee
* date : 2023/06/11
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/06/11 crlee
*/
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private EgovJwtTokenUtil jwtTokenUtil;
public static final String HEADER_STRING = "Authorization";
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
boolean verificationFlag = true;
// step 1. request header에서 토큰을 가져온다.
String jwtToken = EgovStringUtil.isNullToString(req.getHeader(HEADER_STRING));
if(Checks.isEmpty(jwtToken)){
chain.doFilter(req, res);
return;
}
// step 2. 토큰에 내용이 있는지 확인해서 id값을 가져옴
// Exception 핸들링 추가처리 (토큰 유효성, 토큰 변조 여부, 토큰 만료여부)
// 내부적으로 parse하는 과정에서 해당 여부들이 검증됨
String id = null;
try {
id = jwtTokenUtil.getUserIdFromToken(jwtToken);
if (id == null) {
logger.debug("jwtToken not validate");
verificationFlag = false;
}
logger.debug("===>>> id = " + id);
} catch (IllegalArgumentException | ExpiredJwtException | MalformedJwtException | UnsupportedJwtException | SignatureException e) {
logger.debug("Unable to verify JWT Token: " + e.getMessage());
verificationFlag = false;
}
LoginVO loginVO = new LoginVO();
if( verificationFlag ){
logger.debug("jwtToken validated");
loginVO.setId(id);
loginVO.setUserSe( jwtTokenUtil.getUserSeFromToken(jwtToken) );
loginVO.setUniqId( jwtTokenUtil.getInfoFromToken("uniqId",jwtToken) );
loginVO.setOrgnztId( jwtTokenUtil.getInfoFromToken("orgnztId",jwtToken) );
loginVO.setName( jwtTokenUtil.getInfoFromToken("name",jwtToken) );
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginVO, null,
Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(req, res);
}
}

@ -0,0 +1,45 @@
package egovframework.com.security;
import egovframework.com.cmm.LoginVO;
import org.springframework.core.MethodParameter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* fileName : CustomAuthenticationPrincipalResolver
* author : crlee
* date : 2023/07/13
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/07/13 crlee
*/
public class CustomAuthenticationPrincipalResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class) &&
parameter.getParameterType().equals(LoginVO.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null ||
authentication.getPrincipal() == null ||
"anonymousUser".equals(authentication.getPrincipal())
) {
return new LoginVO();
}
return authentication.getPrincipal();
}
}

@ -0,0 +1,90 @@
package egovframework.com.security;
import egovframework.com.jwt.JwtAuthenticationEntryPoint;
import egovframework.com.jwt.JwtAuthenticationFilter;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* fileName : SecurityConfig
* author : crlee
* date : 2023/06/10
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/06/10 crlee
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig implements WebMvcConfigurer {
//Http Methpd : Get 인증예외 List
private String[] AUTH_GET_WHITELIST = {
"/schedule/daily", //일별 일정 조회
"/schedule/week", //주간 일정 조회
"/schedule/{schdulId}", //일정 상세조회
};
// 인증 예외 List
@Value("${app.spring.security.white-list}")
private String[] AUTH_WHITELIST;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new CustomAuthenticationPrincipalResolver());
}
@Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationFilter();
}
// @Bean
// protected CorsConfigurationSource corsConfigurationSource() {
// CorsConfiguration configuration = new CorsConfiguration();
//
// configuration.setAllowedOriginPatterns(Arrays.asList("*"));
// configuration.setAllowedMethods(Arrays.asList("HEAD","POST","GET","DELETE","PUT"));
// configuration.setAllowedOrigins(Arrays.asList(ORIGINS_WHITELIST));
// configuration.setAllowedHeaders(Arrays.asList("*"));
// configuration.setAllowCredentials(true);
//
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// source.registerCorsConfiguration("/**", configuration);
// return source;
// }
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.antMatchers(AUTH_WHITELIST).permitAll()
.antMatchers(HttpMethod.GET,AUTH_GET_WHITELIST).permitAll()
.anyRequest().authenticated()
).sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.cors().and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exceptionHandlingConfigurer ->
exceptionHandlingConfigurer
.authenticationEntryPoint(new JwtAuthenticationEntryPoint())
)
.build();
}
}

@ -0,0 +1,89 @@
package kr.xit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.ComponentScan;
import kr.xit.core.spring.config.support.CustomBeanNameGenerator;
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* description : ens API application main
* ServletComponentScan
* - 릿(, 릿, )
* - WebFilter, WebServlet, WebListener annotaion sacan
* - SpringBoot
* ConfigurationPropertiesScan
* - ConfigurationProperties annotaion class scan
* - EnableConfigurationProperties
* packageName : kr.xit
* fileName : EnsAdminApplication
* author : julim
* date : 2023-04-28
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-04-28 julim
*
* </pre>
*/
@Slf4j
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = {"egovframework", "kr.xit"})
@ServletComponentScan
@ComponentScan(
nameGenerator = CustomBeanNameGenerator.class,
basePackages = {"egovframework", "kr.xit"}
)
public class EnsAdminApplication {
static final List<String> basePackages = new ArrayList<>(
Arrays.asList("egovframework", "kr.xit")
);
public static void main(String[] args) {
final String line = "====================================================================";
log.info(line);
log.info("==== EnsAdminApplication start :: active profiles - {} ====", System.getProperty("spring.profiles.active"));
if(Objects.isNull(System.getProperty("spring.profiles.active"))) {
log.error(">>>>>>>>>>>>>> Undefined start VM option <<<<<<<<<<<<<<");
log.error(">>>>>>>>>>>>>> -Dspring.profiles.active=local|dev|prd <<<<<<<<<<<<<<");
log.error("============== EnsAdminApplication start fail ===============");
log.error(line);
System.exit(-1);
}
log.info(line);
// beanName Generator 등록 : API v1, v2 등으로 분류하는 경우
// Bean 이름 식별시 풀패키지 명으로 식별 하도록 함
final CustomBeanNameGenerator beanNameGenerator = new CustomBeanNameGenerator();
beanNameGenerator.addBasePackages(basePackages);
final SpringApplicationBuilder applicationBuilder = new SpringApplicationBuilder(EnsAdminApplication.class);
applicationBuilder.beanNameGenerator(beanNameGenerator);
final SpringApplication application = applicationBuilder.build();
application.setBannerMode(Banner.Mode.OFF);
application.setLogStartupInfo(false);
//TODO : 이벤트 실행 시점이 Application context 실행 이전인 경우 리스너 추가
//PID(Process ID 작성)
application.addListeners(new ApplicationPidFileWriter()) ;
application.run(args);
log.info("=========================================================================================");
log.info("========== EnsAdminApplication load Complete :: active profiles - {} ==========", System.getProperty("spring.profiles.active"));
log.info("=========================================================================================");
}
}

@ -0,0 +1,27 @@
package kr.xit.biz.auth.mapper;
import egovframework.com.cmm.LoginVO;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
/**
* <pre>
* description :
*
* packageName : kr.xit.biz.auth.mapper
* fileName : IAuthApiMapper
* author : limju
* date : 2023-05-11
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-05-11 limju
*
* </pre>
*/
@Mapper
public interface IAuthApiMapper {
LoginVO actionLogin(LoginVO vo);
// LoginVO searchId(LoginVO vo);
// LoginVO searchPassword(LoginVO vo);
// void updatePassword(LoginVO vo);
}

@ -0,0 +1,40 @@
package kr.xit.biz.auth.service;
import egovframework.com.cmm.LoginVO;
import egovframework.com.cmm.util.EgovFileScrty;
import javax.annotation.Resource;
import kr.xit.biz.auth.mapper.IAuthApiMapper;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class AuthApiService extends EgovAbstractServiceImpl implements IAuthApiService {
@Resource
private IAuthApiMapper mapper;
/**
*
* @param vo LoginVO
* @return LoginVO
*/
@Override
public LoginVO actionLogin(LoginVO vo) {
// 1. 입력한 비밀번호를 암호화한다.
String enpassword = EgovFileScrty.encryptPassword(vo.getPassword(), vo.getId());
vo.setPassword(enpassword);
// 2. 아이디와 암호화된 비밀번호가 DB와 일치하는지 확인한다.
LoginVO loginVO = mapper.actionLogin(vo); //loginDAO.actionLogin(vo);
// 3. 결과를 리턴한다.
if (loginVO != null && !loginVO.getId().equals("") && !loginVO.getPassword().equals("")) {
return loginVO;
} else {
loginVO = new LoginVO();
}
return loginVO;
}
}

@ -0,0 +1,32 @@
package kr.xit.biz.auth.service;
import egovframework.com.cmm.LoginVO;
/**
*
* @author
* @since 2009.03.06
* @version 1.0
* @see
*
* <pre>
* << (Modification Information) >>
*
*
* ------- -------- ---------------------------
* 2009.03.06
* 2011.08.31 JJY 릿
*
* </pre>
*/
public interface IAuthApiService {
/**
*
*
* @param vo LoginVO
* @return LoginVO
*/
LoginVO actionLogin(LoginVO vo);
}

@ -0,0 +1,194 @@
package kr.xit.biz.auth.web;
import egovframework.com.cmm.LoginVO;
import egovframework.com.jwt.EgovJwtTokenUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import kr.xit.biz.auth.service.IAuthApiService;
import kr.xit.core.consts.Constants;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.model.IApiResponse;
import kr.xit.core.spring.util.MessageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
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.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
/**
* <pre>
* description :
*
* packageName : kr.xit.biz.auth
* fileName : AuthApiController
* author : limju
* date : 2023-04-26
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-04-26 limju
*
* </pre>
* @see
*/
@Tag(name = "AuthApiController", description = "인증 관리")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/biz/auth")
public class AuthApiController {
@Value("${app.token.saveType:header}")
private String authSaveType;
/** EgovLoginService */
private final IAuthApiService loginService;
/** EgovMessageSource */
private final MessageUtil messageUtil;
private final EgovJwtTokenUtil egovJwtTokenUtil;
/**
*
* @param loginVO , LoginVO
* @param request HttpServletRequest
* @return ()
*/
@io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true,
content = {
@Content(
mediaType = "application/json",
examples = {
@ExampleObject(value = """
{
"id": "admin",
"password": "1",
"userSe": "USR"
}
""")
}
)
}
)
@Operation(summary = "로그인" , description = "로그인")
@PostMapping(value = "/login", consumes = {MediaType.APPLICATION_JSON_VALUE , MediaType.TEXT_HTML_VALUE})
public IApiResponse login(@RequestBody final LoginVO loginVO, HttpServletRequest request) {
// 1. 일반 로그인 처리
LoginVO loginResultVO = loginService.actionLogin(loginVO);
if (loginResultVO != null && loginResultVO.getId() != null && !loginResultVO.getId().equals("")) {
request.getSession().setAttribute(Constants.AuthSaveSession.LOGIN_VO.getCode(), loginResultVO);
return ApiResponseDTO.success(loginResultVO);
}
return ApiResponseDTO.success(messageUtil.getMessage("fail.common.login"));
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(
required = true,
content = {
@Content(
mediaType = "application/json",
examples = {
@ExampleObject(
name = "admin",
description = "admin",
value = """
{
"id": "admin",
"password": "1",
"userSe": "USR"
}
"""),
@ExampleObject(
name = "admin1",
description = "admin1",
value = """
{
"id": "admin1",
"password": "1",
"userSe": "USR"
}
""")
}
)
}
)
@Operation(summary = "로그인(JWT)" , description = "로그인(JWT)")
@PostMapping(value = "/loginJwt")
public IApiResponse loginJWT(@RequestBody final LoginVO loginVO, HttpServletRequest request) {
HashMap<String, Object> resultMap = new HashMap<String, Object>();
// 1. 일반 로그인 처리
LoginVO loginResultVO = loginService.actionLogin(loginVO);
if (loginResultVO != null && loginResultVO.getId() != null && !loginResultVO.getId().equals("")) {
Map<String, Object> claimsMap = new HashMap<>();
// claimsMap.put("dkkdk", "kdkkdkdkd");
String jwtToken = egovJwtTokenUtil.generateToken(loginVO, claimsMap);
// String jwtToken = egovJwtTokenUtil.generateToken(loginVO.getId());
String username = egovJwtTokenUtil.getUsernameFromToken(jwtToken);
// System.out.println("Dec jwtToken username = "+username);
//서버사이드 권한 체크 통과를 위해 삽입
//EgovUserDetailsHelper.isAuthenticated() 가 그 역할 수행. DB에 정보가 없으면 403을 돌려 줌. 로그인으로 튕기는 건 프론트 쪽에서 처리
request.getSession().setAttribute(Constants.AuthSaveSession.LOGIN_VO.getCode(), loginResultVO);
// UsernamePasswordAuthenticationToken authenticationToken = jwtTokenProvider.toAuthentication(loginVO.getId(), loginVO.getPassword());
// Authentication authentication = authenticationManager.authenticate(authenticationToken);
//
//
// // Authentication 저장
// if(Objects.equals(authSaveType, Constants.AuthSaveType.SECURITY.getCode())){
// // TODO :: SessionCreationPolicy.STATELESS 인 경우 사용 불가
// SecurityContextHolder.getContext().setAuthentication(authentication);
//
// }else if(Objects.equals(authSaveType, Constants.AuthSaveType.SESSION.getCode())){
// session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
// }
//Map<String, Object> infoMap = new HashMap<>();
//infoMap.put(Constants.JwtToken.TOKEN_USER_ID.getCode(), loginVO.getId());
//infoMap.put(Constants.JwtToken.TOKEN_USER_MAIL.getCode(), loginVO.getEmail());
//String jwtToken = jwtTokenProvider.generateJwtAccessToken(authentication, infoMap);
//String jwtToken = jwtTokenProvider.generateJwtAccessToken(loginVO.getId(), "ROLE_USER");
resultMap.put("resultVO", loginResultVO);
resultMap.put("token", jwtToken);
return ApiResponseDTO.success(resultMap);
}
return ApiResponseDTO.error(messageUtil.getMessage("fail.common.login") );
}
/**
* .
* @return resultVO
* @exception Exception
*/
@Operation(summary = "logout" , description = "로그아웃")
@GetMapping(value = "/logout")
public IApiResponse actionLogoutJSON(HttpServletRequest request) {
RequestContextHolder.currentRequestAttributes().removeAttribute(Constants.AuthSaveSession.LOGIN_VO.getCode(), RequestAttributes.SCOPE_SESSION);
return ApiResponseDTO.empty();
}
}

@ -0,0 +1,191 @@
package kr.xit.core.aop;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.servlet.http.HttpServletRequest;
import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.support.utils.Checks;
import kr.xit.core.support.utils.JsonUtils;
import kr.xit.core.support.utils.LogUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* <pre>
* description : logging trace aspect
* core LoggerAspect -> traceLogging / traceLoggingError / traceLoggingResult
*
* Logging trace
* - MDC(Mapped Diagnostic Context : logback, log4j )
* - ThreadLocal
* - nginx : proxy_set_header X-RequestID $request_id;
* - logback log pattern : [traceId=%X{request_id}]
*
* app.slack-webhook.enabled: true slack push
* Slack webhook : SlackWebhookPush
*
* packageName : kr.xit.core.aop
* fileName : TraceLoggerAspect
* author : julim
* date : 2023-04-28
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-04-28 julim
* 2023-06-12 julim RequestContextHolder.HttpServletRequest
* </pre>
* @see kr.xit.core.support.slack.SlackWebhookPush#sendSlackAlertLog(String, String, String)
*/
@Slf4j
@Aspect
@Component
public class TraceLoggerAspect {
@Value("${app.log.request.custom-enabled:false}")
private boolean isReqLogEnabled;
// 응답결과 로그
@Value("${app.log.response-enabled:false}")
private boolean isResLogEnabled;
@Pointcut("execution(public * egovframework..web.*.*(..)) || execution(public * kr.xit..web.*.*(..))")
public void requestPointCut() {
}
@Pointcut("execution(public * egovframework..*.*(..)) || execution(public * kr.xit..*.*(..))")
public void errorPointCut() {
}
@Pointcut("execution(public * egovframework..web.*.*(..)) || execution(public * kr.xit..web.*.*(..))")
public void resultPointCut() {
}
@Before(value = "requestPointCut()")
public void logBefore(JoinPoint joinPoint) {
if(!isReqLogEnabled) return;
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes != null? attributes.getRequest(): null;
assert request != null;
requestLog(request, getParams(request));
}
@AfterReturning(pointcut = "resultPointCut()", returning = "result")
public void logAfterReturning(final JoinPoint jp, final Object result) {
if(isResLogEnabled) {
log.info("{}{}{}",
"\n//============================= Http Response ==============================",
LogUtils.toString(result),
"\n=========================================================================//"
);
}
}
@AfterThrowing(value = "errorPointCut()", throwing="error")
public void afterThrowingProceed(final JoinPoint jp, final Throwable error) {
//traceApiLoggingError(jp, error);
}
private String getResult(final Object o){
//noinspection rawtypes
if(o instanceof Future future) {
try {
return JsonUtils.toJson(future.get());
} catch (InterruptedException ie){
// thread pool에 에러 상태 전송
Thread.currentThread().interrupt();
throw BizRuntimeException.create(ie);
} catch (ExecutionException ee) {
throw BizRuntimeException.create(ee);
}
}else{
return JsonUtils.toJson(o);
}
}
private void requestLog(HttpServletRequest request, JSONObject params) {
if (log.isDebugEnabled()) {
Map<String, Object> map = new LinkedHashMap<>();
//sb.append("Ajax Call : " + "XMLHttpRequest".equals(request.getHeader(Globals.AJAX_HEADER))).append("\n");
map.put("URI", request.getRequestURI());
map.put("URL", request.getRequestURL());
map.put("IP", request.getRemoteAddr());
map.put("Referer URI", request.getHeader("referer"));
map.put("Method", request.getMethod());
map.put("User Agent", request.getHeader("User-Agent"));
map.put("Session", request.getSession().getId());
map.put("Locale", request.getLocale().getCountry());
map.put("ContentType", request.getContentType());
map.put("Parameters", params);
log.info("{}{}{}",
"\n//============================= Http Request ==============================",
LogUtils.toString(map),
"\n=========================================================================//"
);
map.clear();
}
}
@SuppressWarnings("unchecked")
private JSONObject getParams(HttpServletRequest request) {
JSONObject jsonObject = new JSONObject();
Enumeration<String> params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = params.nextElement();
String replaceParam = param.replaceAll("\\.", "-");
jsonObject.put(replaceParam, maskingParam(replaceParam, request.getParameter(param)));
}
return jsonObject;
}
private String maskingParam(final String key, final String value){
if(Checks.isEmpty(value)) return value;
if("juminId".equals(key)) {
if(value.length() == 14) {
return value.replaceAll("([0-9]{6})-([1-4]{1})([0-9]{6})", "$1-$2******");
}
return value.replaceAll("([0-9]{6})([1-4]{1})([0-9]{6})", "$1$2******");
}
if("telNo".equals(key)) {
if(value.contains("-")){
return value.replaceAll("-[0-9]{3,4}-", "-****-");
};
return value.replaceAll("([0-9]{3})([0-9]{4})([0-9]{4})", "$1$2****");
}
if("email".equals(key)) {
return value.replaceAll("[a-z,A-Z,0-9]+@", "******@");
}
if("name".equals(key)) {
return value.replaceAll("(?<=.{1}).", "*");
}
return value;
}
@SuppressWarnings("unchecked")
private String resetJsonMasking(final JSONObject json){
for (Object key : json.keySet()) {
if(Checks.isEmpty(json.get(key))) {
json.put(key, json.get(key));
}else {
json.put(key, maskingParam((String) key, String.valueOf(json.get(key))));
}
}
return json.toJSONString();
}
}

@ -0,0 +1,35 @@
package kr.xit.core.spring.config;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <pre>
* description : Springdoc(swagger)
*
* packageName : kr.xit.core.spring.config
* fileName : SpringDocsConfig
* author : julim
* date : 2023-04-28
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-04-28 julim
*
* </pre>
*/
@ConditionalOnProperty(value = "springdoc.swagger-ui.enabled", havingValue = "true", matchIfMissing = false)
@Configuration
public class SpringDocsApiConfig {
@Bean
public GroupedOpenApi authentification() {
return GroupedOpenApi.builder()
.group("1. Authentification API")
.pathsToMatch(
"/biz/auth/**"
)
.build();
}
}

@ -0,0 +1,47 @@
package kr.xit.core.spring.util;
import kr.xit.core.spring.config.support.ApplicationContextProvider;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.context.ApplicationContext;
/**
* <pre>
* description : Get Bean Object
* Filter / Interceptor Bean
* (Bean @Autowired / @Resource )
* packageName : kr.xit.core.spring.util
* fileName : AdminSpringUtils
* author : julim
* date : 2023-04-28
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-04-28 julim
*
* </pre>
* @see ApplicationContextProvider
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AdminSpringUtils {
public static ApplicationContext getApplicationContext() {
return ApplicationContextProvider.getApplicationContext();
}
public static boolean containsBean(String beanName) {
return getApplicationContext().containsBean(beanName);
}
public static Object getBean(String beanName) {
return getApplicationContext().getBean(beanName);
}
public static Object getBean(Class<?> clazz) {
return getApplicationContext().getBean(clazz);
}
// public static ICmmEnsCacheService getCmmEnsCacheService(){
// return (ICmmEnsCacheService)getBean(CmmEnsCacheService.class);
// }
}

@ -0,0 +1,44 @@
#-----------------------------------------------------------------------
# application 설정
#-----------------------------------------------------------------------
app:
#---------------------------------------------------------------
# log 설정
# request:
# custom-enabled | common-enabled | filter-enabled 중 1개만 활성화
# --> 운영: common-enabled, 개발: custom-enabled 사용 권장
# response-enabled : 호출 결과 출력 - 운영시 false
# mdc : api 호출(서비스) 로그 기록
# uris : api 호출 로그 제외 패턴
#---------------------------------------------------------------
log:
request:
# exclude pattern : CommonsRequestLoggingFilter && LoggingFilter 적용
exclude-patterns: '/swagger-ui/(.*), /api-docs/(.*), /favicon.ico'
custom-enabled: false
# CommonsRequestLoggingFilter 사용 parameter 로그 출력
common-enabled: false
# Filter를 사용한 로그 출력
filter-enabled: false
response-enabled: false
mdc:
enabled: true
exclude-patterns: '/api/kakao/(.*), /api/v1/ens/sendBulks(.*)'
# slack
slack-webhook:
enabled: false
url: https://hooks.slack.com/services/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
ssh:
host: 192.168.200.52
port: 22
id: administrator
passwd: 1q2w3e4r5t!
sg:
root-path: /SMSImage
ens-path: /ENSData
rcv: /
backup: /backup
err: /err

@ -0,0 +1,103 @@
#-----------------------------------------------------------------------
# dev 설정
#-----------------------------------------------------------------------
spring:
datasource:
hikari:
# 9 server
primary:
database: mysql
driver-class-name: org.mariadb.jdbc.Driver
jdbc-url: jdbc:mariadb://211.119.124.9:4407/mens?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&autoReconnect=true
username: root
password: xit1807
read-only: false
# multi-database
#secondary:
devtools:
livereload:
enabled: true
springdoc:
api-docs:
enabled: true
swagger-ui:
enabled: true
logging:
level:
root: debug
org.apache.http: warn
io.netty: warn
reactor.netty: WARN
# webclient logging
reactor.netty.http.client: DEBUG
#org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE
org.springframework: warn
org.hibernate.validator.internal: WARN
file:
# 로그파일 위치
path: ${app.data.root.path}/mens/logs
name: ${app.name}
# ==================================================================================================================
# SQL logging lib setting
# ==================================================================================================================
decorator:
datasource:
p6spy:
enable-logging: true
app:
api-ip: 211.119.124.9
# 강제로 swagger-url을 지정해야 하는 경우만 선언
#swagger-url: 'http://localhost:${server.port}${server.servlet.context-path:}/'
# Spring Security cors 설정 :: CorsConfiguration 설정 값
cors:
allowed-origins: http://localhost:8080, http://${app.api-ip}:8080, http://localhost:8082, http://${app.api-ip}:8082
data:
root:
path: /data
#---------------------------------------------------------------
# log 설정
# request:
# custom-enabled | common-enabled | filter-enabled 중 1개만 활성화
# --> 운영: common-enabled, 개발: custom-enabled 사용 권장
# response-enabled : 호출 결과 출력 - 운영시 false
# mdc : api 호출(서비스) 로그 기록
# uris : api 호출 로그 제외 패턴
#---------------------------------------------------------------
log:
request:
custom-enabled: true
response-enabled: true
# MDC logging trace 활성
mdc:
enabled: true
# slack
slack-webhook:
enabled: false
url: https://hooks.slack.com/services/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
contract:
# milisecond
connection:
timeout: 60000
readTimeout: 60000
kt:
host: http://211.43.10.163:10210/ONLWeb
api:
# 모바일페이지 : 본문자수신등록 callback url - 토큰인증확인 조회, 열람확인결과 전송
dp-callback-url: http://${app.api-ip}:8081/api/biz/mbl/v1/kt/dpMblPage
me-callback-url: http://${app.api-ip}:8081/api/biz/mbl/v1/kt/meMblPage
# 수신거부상태전송 : BC-AG-SN-014
refuse-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/refuse
# 수신동의상태전송 : BC-AG-SN-015
approve-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/approve

@ -0,0 +1,88 @@
#-----------------------------------------------------------------------
# application 설정
#-----------------------------------------------------------------------
app:
contract:
# milisecond
connection:
timeout: 120000
readTimeout: 120000
thread:
# 동시 실행 스레드 개수
corePoolSize: 5
# 스레드 풀에서 사용할 수 있는 최대 개수
maxPoolSize: 10
kakao:
bulk-max-cnt: 10
host: https://docs-gw.kakaopay.com
# token: dd394da7f66211eb9cbe46e139ceffc2
# uuid: CON-41ef0535f67211ebbdedd2e6ed332381
api:
send: /v1/documents;POST
validToken: /v1/{document_binder_uuid}/tokens/{tokens};GET
modifyStatus: /v1/documents/{document_binder_uuid};POST
findStatus: /v1/documents/{document_binder_uuid}/status;GET
bulksend: /v1/documents/bulk;POST
bulkstatus: /v1/documents/bulk/status;POST
nice:
host: https://svc.niceapi.co.kr:22001
# signgu-code: 11000
# ffnlg-code: 11
# client-id: 6c3eb1ff-530d-458a-9a6e-e02e3346f679
# client-secret: 960f204ec45bb312b7ad2d6b54b984d9c353b8
# product-id: 2101466024
api:
generate-token: /digital/niceid/oauth/oauth/token
revoke-token: /digital/niceid/oauth/oauth/token/revokeById
publickey: /digital/niceid/api/v1.0/common/crypto/publickey
symmetrickey: /digital/niceid/api/v1.0/common/crypto/symmetrickey
ci: /digital/niceid/cert/v1.0/ipin/addinfo/ci
kt:
# vpn 사용
host: http://172.16.0.13:10210/ONLWeb
# 운영
#host: http://172.16.11.182:10210/ONLWeb
api:
# 토큰발행
generate-token: /oauth/token
# 본문자수신등록 : BC-AG-SN-002
main-send: /api/message/main/send
# 토큰인증확인조회 : BC-AG-SN-008
cfm-token: /api/message/token
# 토큰열람확인결과전송 : BC-AG-SN-009
read-token: /api/message/read
# 사전/본 문자 발송/수신 결과 전송 : BC-AG-SN-010
result-message: /api/ag/message/result
# 사전문자수신등록 : BC-AG-SN-001
before-send: /api/message/before/send
# 수신거부등록 : BC-AG-SN-007
blacklist: /api/blacklist
# 백오피스발송통계연계조회 : BC-AG-SN-011
send-sttc: /api/sndsttc
# 백오피스발송결과연계조회 : BC-AG-SN-012
send-sttcdtl: /api/sndsttcdtl
# whitelist등록 : BC-AG-SN-013
whitelist: /api/whitelist
# 유통증명서발급처리 : BC-AG-SM-001
cerf-acmd: /api/message/acmdcerf
# 기관정산화면연계토큰인증 : BC-AG-SM-002
exca-token: /api/auth/excatoken
# 정산연계자료조회 : BC-AG-EC-001
exca: /api/auth/exca
# 전자문서유통정보수치조회 : BC-AG-HS-001
info-acmd: /api/acmdinfo
# 전자문서유통정보수치확인서 발급처리 : BC-AG-HS-002
cfm-acmd: /api/acmdinfocfm
pplus:
host: https://t.postplus.co.kr
api:
# 우편 제작 접수
accept: /po/api/postplusPstMsrApi.do
# 우편 제작 상태 조회
status: /po/api/postplusPstStatusApi.do
epost:
host: http://openapi.epost.go.kr
api:
postTrackInfo: /trace/retrieveLongitudinalCombinedService/retrieveLongitudinalCombinedService/getLongitudinalCombinedList

@ -0,0 +1,129 @@
#-----------------------------------------------------------------------
# local 설정
#-----------------------------------------------------------------------
server:
port: 8444
http: 8080
spring:
datasource:
hikari:
# 9 server
primary:
database: mysql
driver-class-name: org.mariadb.jdbc.Driver
jdbc-url: jdbc:mariadb://211.119.124.9:4407/mens?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&autoReconnect=true
username: root
password: xit1807
read-only: false
# multi-database
#secondary:
devtools:
restart:
enabled: true
additional-exclude: static/**,public/**
livereload:
enabled: true
springdoc:
api-docs:
enabled: true
swagger-ui:
enabled: true
logging:
level:
root: debug
org.apache.http: warn
io.netty: warn
reactor.netty: WARN
# webclient logging
reactor.netty.http.client: DEBUG
#org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE
org.springframework: warn
org.hibernate.validator.internal: WARN
file:
# 로그파일 위치
path: ${app.data.root.path}/mens/logs
name: ${app.name}
# Spring Security cors 설정 :: CorsConfiguration 설정 값
cors:
allowed-origins: http://localhost:8080, http://${app.api-ip}:8080, http://localhost:8082, http://${app.api-ip}:8082
# ==================================================================================================================
# SQL logging lib setting
# ==================================================================================================================
decorator:
datasource:
p6spy:
enable-logging: true
app:
api-ip: 211.119.124.73
# 강제로 swagger-url을 지정해야 하는 경우만 선언
#swagger-url: 'http://localhost:${server.port}${server.servlet.context-path:}/'
# Spring Security cors 설정 :: CorsConfiguration 설정 값
cors:
allowed-origins: http://localhost:8080, http://${app.api-ip}:8080, http://localhost:8082, http://${app.api-ip}:8082
data:
root:
#path: /Users/minuk/data
path: d:/data
#---------------------------------------------------------------
# log 설정
# request:
# custom-enabled | common-enabled | filter-enabled 중 1개만 활성화
# --> 운영: common-enabled, 개발: custom-enabled 사용 권장
# response-enabled : 호출 결과 출력 - 운영시 false
# mdc : api 호출(서비스) 로그 기록
# uris : api 호출 로그 제외 패턴
#---------------------------------------------------------------
log:
request:
custom-enabled: true
response-enabled: true
# MDC logging trace 활성
mdc:
enabled: true
# slack
slack-webhook:
enabled: false
url: https://hooks.slack.com/services/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
ssh:
host: 211.119.124.9
port: 22
id: xituser
passwd: xituser!@
sg:
root-path: /data/mens/sg-pni-cctv
ens-path: /data/mens/sg-ens-cctv
rcv: /rcv
backup: /backup
err: /err
contract:
# milisecond
connection:
timeout: 60000
readTimeout: 60000
kt:
# vpn 사용
#host: http://172.16.0.13:10210/ONLWeb
host: http://211.43.10.163:10210/ONLWeb
api:
# 모바일페이지 : 본문자수신등록 callback url - 토큰인증확인 조회, 열람확인결과 전송
dp-callback-url: http://${app.api-ip}:8080/api/web/mbl/v1/kt/dpMblPage.do
me-callback-url: http://${app.api-ip}:8080/api/web/mbl/v1/kt/meMblPage.do
#dp-callback-url: http://211.119.124.73:8081/api/biz/mbl/v1/kt/dpMblPage
#me-callback-url: http://211.119.124.73:8081/api/biz/mbl/v1/kt/meMblPage
# 수신거부상태전송 : BC-AG-SN-014
refuse-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/refuse
# 수신동의상태전송 : BC-AG-SN-015
approve-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/approve

@ -0,0 +1,105 @@
#-----------------------------------------------------------------------
# prod 설정
#-----------------------------------------------------------------------
spring:
datasource:
hikari:
# 9 server
primary:
database: mysql
driver-class-name: org.mariadb.jdbc.Driver
# jdbc:mariadb://127.0.0.1:4407/mens?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&autoReconnect=true
jdbc-url: ENC(N7TRplIpBBUbXtSi8fx0wr92OdMgvp9Iw5tmaW7EUaH6ialiAWohx+rOEZx/j+OHFkJSrhYQElPIVe5r4d0tWDNREpgvKwxZRTGXhNdTMMUUHonkGKfB7bURxMfjuMSQEUdKicPZv+xB9eGlwcuPpgC7vaQuZM6WrUDP31+6qYboTUQKBK/7lg==)
username: ENC(wgnjrc4VB7R3I+OwMV+iXQ==)
password: ENC(+sXCmhmSV3Q/3KgOnmpnTQ==)
read-only: false
# multi-database
#secondary:
devtools:
livereload:
enabled: false
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: false
logging:
level:
root: warn
org.apache.http: warn
io.netty: warn
reactor.netty: WARN
# webclient logging
reactor.netty.http.client: warn
#org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE
org.springframework: warn
org.hibernate.validator.internal: WARN
file:
# 로그파일 위치
path: ${app.data.root.path}/mens/logs
name: ${app.name}
# ==================================================================================================================
# SQL logging lib setting
# ==================================================================================================================
decorator:
datasource:
p6spy:
enable-logging: true
app:
api-ip: 103.145.215.46
# 강제로 swagger-url을 지정해야 하는 경우만 선언
swagger-url: 'http://103.145.215.46:8081/${server.servlet.context-path:}/'
# Spring Security cors 설정 :: CorsConfiguration 설정 값
cors:
allowed-origins: http://localhost, http://${app.api-ip}, http://localhost:8082, http://${app.api-ip}:8082, https://ens.sisul.or.kr
data:
root:
path: /data
#---------------------------------------------------------------
# log 설정
# request:
# custom-enabled | common-enabled | filter-enabled 중 1개만 활성화
# --> 운영: common-enabled, 개발: custom-enabled 사용 권장
# response-enabled : 호출 결과 출력 - 운영시 false
# mdc : api 호출(서비스) 로그 기록
# uris : api 호출 로그 제외 패턴
#---------------------------------------------------------------
log:
request:
common-enabled: true
response-enabled: false
# MDC logging trace 활성
mdc:
enabled: true
# slack
slack-webhook:
enabled: false
url: https://hooks.slack.com/services/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
contract:
# milisecond
connection:
timeout: 20000
readTimeout: 20000
kt:
# vpn 사용
#host: http://172.16.0.13:10210/ONLWeb
# 운영
host: http://172.16.11.182:10210/ONLWeb
api:
# 모바일페이지 : 본문자수신등록 callback url - 토큰인증확인 조회, 열람확인결과 전송
dp-callback-url: https://ens.sisul.or.kr/api/web/mbl/v1/kt/dpMblPage.do
me-callback-url: https://ens.sisul.or.kr/api/web/mbl/v1/kt/meMblPage.do
# 수신거부상태전송 : BC-AG-SN-014
refuse-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/refuse
# 수신동의상태전송 : BC-AG-SN-015
approve-rcv: http://${app.api-ip}:8081/api/ens/kt/v1/receive/approve

@ -0,0 +1,101 @@
#-----------------------------------------------------------------------
#
# egovframework 설정
# api 공통 설정
#-----------------------------------------------------------------------
Globals:
# DB서버 타입(hsql,mysql,oracle,altibase,tibero) - datasource 및 sqlMap 파일 지정에 사용됨
DbType: mysql
# MainPage Setting
MainPage: /cmm/main/mainPage.do
#server.servlet.context-path=/sht_boot_web
server:
port: 8080
error:
whitelabel:
enabled: false
app:
name: mens-admin
# springdoc url 정보
desc: 모바일 전자고지 Administrator
# spring security ignore
spring:
security:
white-list:
/,
/biz/auth/**,
/api-docs/**,
/swagger-resources,
/swagger-ui.html,
/swagger-ui/**
data:
root:
path: /data
file:
cmm:
temp-path: ${app.data.root.path}/temp
upload:
root: ${app.data.root.path}
# root: /data
# E-GREEN 우편 발송
post: /post/rcv/
spring:
main:
# 순환참조 에러 무시
allow-circular-references: true
pid:
file: ${app.data.root.path}/${app.name}.pid
profiles:
active: '@springProfilesActive@'
# core의 application-common.yml과 application-auth.yml include
include:
- https
- common
- auth
- app
- ens
batch:
jdbc:
initialize-schema: NEVER #NEVER|ALWAYS
# JPA does not support custom isolation levels, so locks may not be taken when launching Jobs.
# To silence this warning, set 'spring.batch.jdbc.isolation-level-for-create' to 'default'.
isolation-level-for-create: default
job:
enabled: false
#-----------------------------------------------------------------
# xit framework 설정
#-----------------------------------------------------------------
datasource:
#type: com.zaxxer.hikari.HikariDataSource
hikari:
primary:
pool-name: xit-maria-pool
auto-commit: false
# 인프라의 적용된 connection time limit보다 작아야함
max-lifetime: 1800000
maximum-pool-size: 15
minimum-idle: 5
#transaction-isolation: TRANSACTION_READ_UNCOMMITTED
data-source-properties:
rewriteBatchedStatements: true
# secondary:
# pool-name: xit-oracle-pool
# auto-commit: false
# # 인프라의 적용된 connection time limit보다 작아야함
# max-lifetime: 1800000
# maximum-pool-size: 15
# minimum-idle: 5
## transaction-isolation: TRANSACTION_READ_UNCOMMITTED
# data-source-properties:
# rewriteBatchedStatements: true
logging:
level:
root: error

@ -0,0 +1,382 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.org (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
To suppress certain violations please review suppression filters.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<module name="SuppressWarningsFilter"/>
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/filefilters/index.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- https://checkstyle.org/filters/suppressionfilter.html -->
<module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.org/checks/whitespace/index.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
</module>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces">
<property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
<module name="LeftCurly">
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF, LITERAL_SWITCH"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
<property name="id" value="RightCurlyAlone"/>
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/>
</module>
<module name="WhitespaceAfter">
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="4"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="4"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="0"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="NoWhitespaceBeforeCaseDefaultColon"/>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
<property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module>
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad">
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF,
TYPE_EXTENSION_AND "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="InvalidJavadocPosition"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9]\w*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation">
<property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
</module>
<!-- https://checkstyle.org/filters/suppressionxpathfilter.html -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<module name="SuppressWarningsHolder" />
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)" />
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)" />
<property name="checkFormat" value="$1" />
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE.SUPPRESS\: ([\w\|]+)"/>
<!-- $1 refers to the first match group in the regex defined in commentFormat -->
<property name="checkFormat" value="$1"/>
<!-- The check is suppressed in the next line of code after the comment -->
<property name="influenceFormat" value="1"/>
</module>
</module>
</module>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.xit.biz.auth.mapper.IAuthApiMapper">
<!-- 일반 로그인 -->
<select id="actionLogin" resultType="egovframework.com.cmm.LoginVO">
<if test="userSe = 'USR'">
/** auth-mysql-mapper|actionLogin-로그인|julim */
SELECT user_id AS id
, user_nm AS name
, password
, ihidnum
, email_adres AS email
, 'USR' AS userSe
, orgnzt_id
, esntl_id
FROM xit_user_info
WHERE user_id = #{id}
AND password = #{password}
AND user_sttus_code = 'P'
</if>
</select>
</mapper>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
cacheEnabled 설정에서 각 mapper 에 설정된 캐시를 전역적으로 사용할지 말지에 대한 여부 true | false true
lazyLoadingEnabled 늦은 로딩을 사용할지에 대한 여부. 사용하지 않는다면 모두 즉시 로딩할 것이다. 이 값은 fetchType 속성을 사용해서 대체할 수 있다. true | false false
aggressiveLazyLoading 활성화 상태로 두게 되면 늦은(lazy) 로딩 프로퍼티를 가진 객체는 호출에 따라 로드될 것이다. 반면에 개별 프로퍼티는 요청할때 로드된다. true | false true
multipleResultSetsEnabled 한개의 구문에서 여러개의 ResultSet 을 허용할지의 여부(드라이버가 해당 기능을 지원해야 함) true | false true
useColumnLabel 칼럼명 대신에 칼럼라벨을 사용. 드라이버마다 조금 다르게 작동한다. 문서와 간단한 테스트를 통해 실제 기대하는 것처럼 작동하는지 확인해야 한다. true | false true
useGeneratedKeys 생성키에 대한 JDBC 지원을 허용. 지원하는 드라이버가 필요하다. true 로 설정하면 생성키를 강제로 생성한다. 일부 드라이버(예를들면, Derby)에서는 이 설정을 무시한다. true | false False
autoMappingBehavior MyBatis 가 칼럼을 필드/프로퍼티에 자동으로 매핑할지와 방법에 대해 명시. PARTIAL 은 간단한 자동매핑만 할뿐, 내포된 결과에 대해서는 처리하지 않는다. FULL 은 처리가능한 모든 자동매핑을 처리한다. NONE, PARTIAL, FULL PARTIAL
defaultExecutorType 디폴트 실행자(executor) 설정. SIMPLE 실행자는 특별히 하는 것이 없다. REUSE 실행자는 PreparedStatement 를 재사용한다. BATCH 실행자는 구문을 재사용하고 수정을 배치처리한다. SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 데이터베이스로의 응답을 얼마나 오래 기다릴지를 판단하는 타임아웃을 셋팅 양수 셋팅되지 않음(null)
safeRowBoundsEnabled 중첩구문내 RowBound 사용을 허용 true | false False
mapUnderscoreToCamelCase 전통적인 데이터베이스 칼럼명 형태인 A_COLUMN을 CamelCase형태의 자바 프로퍼티명 형태인 aColumn으로 자동으로 매핑하도록 함 true | false False
localCacheScope 마이바티스는 순환참조를 막거나 반복된 쿼리의 속도를 높히기 위해 로컬캐시를 사용한다. 디폴트 설정인 SESSION을 사용해서 동일 세션의 모든 쿼리를 캐시한다. localCacheScope=STATEMENT 로 설정하면 로컬 세션은 구문 실행할때만 사용하고 같은 SqlSession에서 두개의 다른 호출사이에는 데이터를 공유하지 않는다. SESSION | STATEMENT SESSION
jdbcTypeForNull JDBC타입을 파라미터에 제공하지 않을때 null값을 처리한 JDBC타입을 명시한다. 일부 드라이버는 칼럼의 JDBC타입을 정의하도록 요구하지만 대부분은 NULL, VARCHAR 나 OTHER 처럼 일반적인 값을 사용해서 동작한다. JdbcType 이늄. 대부분은 NULL, VARCHAR 나 OTHER 를 공통적으로 사용한다. OTHER
lazyLoadTriggerMethods 늦은 로딩을 야기하는 객체의 메소드를 명시 메소드 이름을 나열하고 여러개일 경우 콤마(,) 로 구분 equals,clone,hashCode,toString
defaultScriptingLanguage 동적으로 SQL을 만들기 위해 기본적으로 사용하는 언어를 명시 타입별칭이나 패키지 경로를 포함한 클래스명 org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
callSettersOnNulls 가져온 값이 null일때 setter나 맵의 put 메소드를 호출할지를 명시 Map.keySet() 이나 null값을 초기화할때 유용하다. int, boolean 등과 같은 원시타입은 null을 셋팅할 수 없다는 점은 알아두면 좋다. true | false false
logPrefix 마이바티스가 로거(logger) 이름에 추가할 접두사 문자열을 명시 문자열 셋팅하지 않음
logImpl 마이바티스가 사용할 로깅 구현체를 명시 이 설정을 사용하지 않으면 마이바티스가 사용할 로깅 구현체를 자동으로 찾는다. SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 셋팅하지 않음
proxyFactory 마이바티스가 늦은 로딩을 처리할 객체를 생성할 때 사용할 프록시 툴을 명시 CGLIB | JAVASSIST CGLIB
-->
<settings>
<!--
Settings 설정 옵션 사이트 참조
-.사이트주소: https://postitforhooney.tistory.com/entry/MyBatisSetting-Mybatis%EC%97%90%EC%84%9C-%ED%95%84%EC%9A%94%ED%95%9C-%EB%B6%80%EB%B6%84%EB%93%A4-setting%EC%9E%90%EB%A3%8C
-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="cacheEnabled" value="true" />
<setting name="jdbcTypeForNull" value="VARCHAR" /><!-- NULL / VARCHAR / OTHER-->
<setting name="callSettersOnNulls" value="true"/> <!-- resultType으로 Map Collection 지정 시 value가 null일 떄 컬럼 누락문제 해결을 위한 설정 -->
<setting name="lazyLoadingEnabled" value="false" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" /><!-- NONE / PARTIAL / FULL-->
<setting name="defaultExecutorType" value="SIMPLE" /><!-- SIMPLE / REUSE / BATCH-->
<setting name="defaultStatementTimeout" value="25" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="localCacheScope" value="SESSION" /><!-- SESSION / STATEMENT-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<setting name="aggressiveLazyLoading" value="true" />
</settings>
<!-- Type Aliases 설정-->
<!-- <typeAliases>-->
<!-- <typeAlias alias="egovMap" type="org.egovframe.rte.psl.dataaccess.util.EgovMap" />-->
<!-- <typeAlias alias="ComDefaultCodeVO" type="egovframework.com.cmm.model.ComDefaultCodeVO" />-->
<!-- <typeAlias alias="comDefaultVO" type="egovframework.com.cmm.model.ComDefaultVO" />-->
<!-- </typeAliases>-->
</configuration>

@ -0,0 +1,68 @@
#------------------------------------------------
# Admin \uBA54\uC138\uC9C0 \uC815\uC758
#------------------------------------------------
fail.api.nice.info=NICE \uC778\uC99D \uC815\uBCF4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
fail.api.nice.token.info=NICE Access token \uC815\uBCF4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
fail.api.nice.revoke.token=\uD1A0\uD070(NICE) \uD3D0\uAE30\uC5D0 \uC2E4\uD328\uD558\uC600\uC2B5\uB2C8\uB2E4
fail.api.nice.invalid.tranId=NICE \uC778\uC99D \uC694\uCCAD\uC5D0 \uC2E4\uD328\uD558\uC600\uC2B5\uB2C8\uB2E4(TRAN_ID \uBD88\uC77C\uCE58)
fail.api.nice.token.invalid.expired=Nice token \uC720\uD6A8\uAE30\uAC04\uC774 \uC798\uBABB\uB418\uC5C8\uC2B5\uB2C8\uB2E4[null].
fail.api.nice.symkey.invalid.expired=Nice \uB300\uCE6D\uD0A4 \uC720\uD6A8\uAE30\uAC04\uC774 \uC798\uBABB\uB418\uC5C8\uC2B5\uB2C8\uB2E4[null].
fail.api.rlaybsnm.info=\uBB38\uC11C\uC911\uACC4\uC790 \uC778\uC99D \uC815\uBCF4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
fail.api.token.invalid.expired={0} access token \uC720\uD6A8\uAE30\uAC04\uC774 \uC798\uBABB\uB418\uC5C8\uC2B5\uB2C8\uB2E4[null].
fail.api.kt.token.request=KT \uD1A0\uD070 \uC694\uCCAD\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
fail.api.excel.upload.data={0} \uBC88\uC9F8 {1} \uC140(\uD544\uB4DC) \uAC12\uC774 \uBD80\uC815\uD655 \uD569\uB2C8\uB2E4[{2} - {3}]
err.api.nice.pubKey.0000=\uACF5\uAC1C\uD0A4\uBC1C\uAE09
err.api.nice.pubKey.0001=\uD544\uC218 \uC785\uB825\uAC12 \uC624\uB958
err.api.nice.pubKey.0003=\uACF5\uAC1C\uD0A4 \uBC1C\uAE09 \uB300\uC0C1 \uD68C\uC6D0\uC0AC \uC544\uB2D8
err.api.nice.pubKey.0099=\uAE30\uD0C0 \uC624\uB958
err.api.nice.symKey.0000=\uB300\uCE6D\uD0A4 \uBC1C\uAE09
err.api.nice.symKey.0001=\uACF5\uAC1C\uD0A4 \uAE30\uAC04 \uB9CC\uB8CC
err.api.nice.symKey.0002=\uACF5\uAC1C\uD0A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C
err.api.nice.symKey.0003=\uACF5\uAC1C\uD0A4\uB97C \uBC1C\uAE09\uD55C \uD68C\uC6D0\uC0AC \uC544\uB2D8
err.api.nice.symKey.0004=\uBCF5\uD638\uD654 \uC624\uB958
err.api.nice.symKey.0005=\uD544\uC218 \uC785\uB825\uAC12 \uC624\uB958(key_version, key_info \uB0B4 \uD544\uC218\uAC12 \uD655\uC778)
err.api.nice.symKey.0006=\uB300\uCE6D\uD0A4 \uB4F1\uB85D \uAC00\uB2A5 \uD68C\uC6D0\uC0AC \uC544\uB2D8
err.api.nice.symKey.0007=key \uC911\uBCF5 \uC624\uB958 (\uD604\uC7AC \uBC0F \uC9C1\uC804\uC5D0 \uC0AC\uC6A9\uD55C key \uC0AC\uC6A9 \uBD88\uAC00)
err.api.nice.symKey.0008=\uC694\uCCAD \uC0AC\uC774\uD2B8 \uCF54\uB4DC\uC640 \uACF5\uAC1C\uD0A4 \uBC1C\uAE09 \uC0AC\uC774\uD2B8 \uCF54\uB4DC \uB2E4\uB984
err.api.nice.symKey.0099=\uAE30\uD0C0 \uC624\uB958
err.api.nice.ci.0000=\uCC98\uB9AC\uC644\uB8CC
err.api.nice.ci.0001=\uB300\uCE6D\uD0A4 \uAE30\uAC04 \uB9CC\uB8CC
err.api.nice.ci.0002=\uB300\uCE6D\uD0A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C
err.api.nice.ci.0003=\uB300\uCE6D\uD0A4\uB97C \uBC1C\uAE09\uD55C \uD68C\uC6D0\uC0AC \uC544\uB2D8
err.api.nice.ci.0004=\uBCF5\uD638\uD654 \uC624\uB958
err.api.nice.ci.0005=\uD544\uC218 \uC785\uB825\uAC12 \uC624\uB958(integrity_value, enc_data \uB0B4 \uD544\uC218\uAC12 \uD655\uC778)
err.api.nice.ci.0006=\uB370\uC774\uD130 \uBB34\uACB0\uC131 \uC624\uB958 (hmac\uAC12 \uBD88\uC77C\uCE58)
err.api.nice.ci.0007=\uC815\uBCF4\uC694\uCCAD\uC720\uD615 \uC785\uB825\uAC12 \uC624\uB958 (info_req_type\uC774 1 \uC544\uB2D8)
err.api.nice.ci.0008=\uC8FC\uBBFC\uBC88\uD638 \uC720\uD6A8\uC131 \uC624\uB958 (\uC0DD\uB144\uC6D4\uC77C \uC720\uD6A8\uC131 \uBC0F \uC22B\uC790 \uC544\uB2D8)
err.api.nice.ci.0009=\uAC70\uB798\uC694\uCCAD\uC2DC\uAC04 \uD3EC\uBA67\uC624\uB958 (req_dtim \uC790\uB9BF\uC218 \uBC0F \uC22B\uC790 \uC544\uB2D8)
err.api.nice.ci.0099=\uAE30\uD0C0 \uC624\uB958
#KT \uC0AC\uC804/\uBCF8 \uBB38\uC790 \uBC1C\uC1A1 \uACB0\uACFC\uCF54\uB4DC : \uD544\uC218 - 2\uC790\uB9AC
info.api.kt.msg.rslt.40=MMS/RCS \uBC1C\uC1A1 \uC218\uC2E0\uC131\uACF5
info.api.kt.msg.rslt.41=MMS\uBC1C\uC1A1 \uBA54\uC2DC\uC9C0 \uB0B4\uC6A9 \uC2A4\uD338
info.api.kt.msg.rslt.42=MMS\uBC1C\uC1A1 \uCC29\uC2E0\uC790 \uC2A4\uD338
info.api.kt.msg.rslt.43=MMS\uBC1C\uC1A1 \uB808\uD3EC\uD2B8 \uC218\uC2E0 \uC2DC\uAC04 \uB9CC\uB8CC(\uBA54\uC2DC\uC9C0\uC804\uC1A1\uD6C4 24\uC2DC\uAC04 \uB808\uD3EC\uD2B8 \uBABB\uBC1B\uB294 \uACBD\uC6B0 )
info.api.kt.msg.rslt.47=MMS\uBC1C\uC1A1 \uBE44\uAC00\uC785\uC790, \uACB0\uBC88, \uC11C\uBE44\uC2A4\uC815\uC9C0
info.api.kt.msg.rslt.48=MMS\uBC1C\uC1A1 \uB2E8\uB9D0\uAE30 \uC804\uC6D0 \uAEBC\uC9D0
info.api.kt.msg.rslt.49=MMS\uBC1C\uC1A1 \uAE30\uD0C0
info.api.kt.msg.rslt.4A=MMS\uBC1C\uC1A1 UNKNOWN/\uB2E8\uB9D0\uAE30\uD615\uC2DD\uC624\uB958(\uC2A4\uD338\uC124\uC815)
info.api.kt.msg.rslt.4D=MMS\uBC1C\uC1A1 \uC804\uC1A1 \uC2E4\uD328(\uBB34\uC120\uB9DD), \uB2E8\uB9D0\uAE30 \uC77C\uC2DC\uC815\uC9C0
info.api.kt.msg.rslt.4J=MMS\uBC1C\uC1A1 \uBE44\uAC00\uC6A9\uD3F0 \uC624\uB958
info.api.kt.msg.rslt.4N=MMS\uBC1C\uC1A1 \uC218\uC2E0\uAC70\uBD80
info.api.kt.msg.rslt.4O=MMS\uBC1C\uC1A1 LMS\uBC1C\uC1A1\uC624\uB958(\uC2DC\uAC04\uCD08\uACFC)
info.api.kt.msg.rslt.4P=MMS\uBC1C\uC1A1 LMS\uBC1C\uC1A1\uC624\uB958(\uAE30\uD0C0)
info.api.kt.msg.rslt.4T=MMS\uBC1C\uC1A1 \uAC00\uC785\uC790\uBBF8\uC874\uC7AC(\uBBF8\uB3D9\uC758\uD3EC\uD568)
info.api.kt.msg.rslt.4Q=MMS\uBC1C\uC1A1 \uC218\uC2E0\uB300\uAE30
info.api.kt.msg.rslt.4R=MMS\uBC1C\uC1A1 \uB2E4\uD68C\uC120 \uC81C\uC678
info.api.kt.msg.rslt.4V=MMS\uBC1C\uC1A1 \uC218\uC2E0\uB4F1\uB85D \uD734\uB300\uD3F0\uBC88\uD638 \uBBF8\uC874\uC7AC
info.api.kt.msg.rslt.4W=MMS\uBC1C\uC1A1 \uAE30\uB3D9\uC758 \uC0AC\uC804\uBB38\uC790 \uC81C\uC678
info.api.kt.msg.rslt.50=\uC218\uC2E0\uD655\uC778 \uC218\uC2E0\uC131\uACF5
#(MMS\uBC1C\uC1A1\uACB0\uACFC\uC21C\uBC88=2, \uC5F4\uB78C\uD0C0\uC784\uC2A4\uD0EC\uD504\uAC00 \uC788\uB294 \uACBD\uC6B0)
info.api.kt.msg.rslt.60=\uC5F4\uB78C\uD655\uC778(MMS\uBC1C\uC1A1\uACB0\uACFC\uCF54\uB4DC=40, \uC5F4\uB78C\uD0C0\uC784\uC2A4\uD0EC\uD504\uAC00 \uC788\uB294 \uACBD\uC6B0)

@ -0,0 +1,3 @@
#------------------------------------------------
# Admin \uBA54\uC138\uC9C0 \uC815\uC758
#------------------------------------------------

@ -0,0 +1,3 @@
#------------------------------------------------
# Admin \uBA54\uC138\uC9C0 \uC815\uC758
#------------------------------------------------

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!--
logback-spring.xml 로 설정시 스프링의 환경변수를 로그백 시스템 환경변수로 사용
logging.file.name => LOG_FILE, logging.file.path => LOG_PATH
logging.charset.console / file => CONSOLE_LOG_CHARSET, FILE_LOG_CHARSET
-->
<!-- async rolling appender 사용시 로그의 class, method, line number 출력 제어 : 성능저하 이슈 -->
<springProfile name="local, dev">
<property name="isIncludeCallerData" value="true"/>
</springProfile>
<springProfile name="prod">
<property name="isIncludeCallerData" value="false"/>
</springProfile>
<!-- ============================================================================= -->
<!-- console logging Appender defined -->
<!-- ============================================================================= -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 기본 출력 로그 제거 -->
<Filter class="kr.xit.core.support.logback.ExcludeLogFilter"/>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>
<!-- ============================================================================= -->
<!-- ============================================================================= -->
<!-- file logging Appender defined -->
<!-- ============================================================================= -->
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${LOG_FILE}.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<!-- 다른 수준의 레벨은 기록하지 않는다.(상위 레벨도 기록 안함), 상위 수준의 레벨에 대한 기록을 원하면 ACCEPT 로 하면 기록된다. -->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!-- 기본 출력 로그 제거 -->
<!--Filter class="kr.xit.core.support.logback.ExcludeLogFilter"/-->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/backup/${LOG_FILE}_%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>30MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>50</maxHistory>
</rollingPolicy>
</appender>
<!-- async appender defined -->
<!-- includeCallerData=true -->
<appender name="ASYNC_ROLLING" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="ROLLING"/>
<!-- blocking queue의 최대 수용 갯수로 기본값은 256 -->
<queueSize>2048</queueSize>
<discardingThreshold>20</discardingThreshold>
<!-- 해당 시간안에 처리하지 못한 이벤트는 삭제 : 단위 - ms -->
<maxFlushTime>6000</maxFlushTime>
<!--큐가 가득찬 상황에서 메세지 유실을 방지하기 위해 application block 할지 여부 -->
<!-- true로 설정된 경우 application을 멈추지 않기 위해 메세지를 버린다 -->
<neverBlock>true</neverBlock>
<!-- 메소드명, 라인번호 출력 : 성능저하 요인 -->
<includeCallerData>${isIncludeCallerData}</includeCallerData>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!-- ============================================================================= -->
<!-- ============================================================================= -->
<!-- logging mask defined -->
<!-- ============================================================================= -->
<appender name="mask" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="kr.xit.core.support.logback.LogbackMaskingPatternLayout">
<maskPattern>\"juminId\"\s*:\s*\"(.*?)\"</maskPattern> <!-- SSN JSON pattern -->
<maskPattern>\"recveJuminno\"\s*:\s*\"(.*?)\"</maskPattern> <!-- SSN JSON pattern -->
<maskPattern>\"recevAddr\"\s*:\s*\"(.*?)\"</maskPattern> <!-- Address JSON pattern -->
<maskPattern>\"recevDetailAddr\"\s*:\s*\"(.*?)\"</maskPattern> <!-- Address JSON pattern -->
<pattern>%-5p [%d{ISO8601,UTC}] [%thread] %c: %m%n%rootException</pattern>
</layout>
</encoder>
</appender>
<!-- ============================================================================= -->
<!-- ************************************************************************* -->
<!-- SQL log : root appender로 로그 전파 - additivity="true" -->
<!-- ************************************************************************* -->
<!-- DB transaction -->
<logger name="org.mybatis.spring.SqlSessionUtils" level="DEBUG" />
<!-- log4jdbc 옵션 설정 -->
<logger name="jdbc" level="OFF"/>
<springProfile name="prod">
<!-- 운영 환경에서만 sql문 및 결과 출력하지 않음 -->
<!-- SQL문과 소요된 시간 -->
<logger name="jdbc.sqltiming" level="OFF"/>
<!-- SQL 결과 조회된 데이터를 table 형식으로 출력 -->
<logger name="jdbc.resultsettable" level="OFF"/>
</springProfile>
<springProfile name="local, dev">
<!-- 로컬, 개발 환경에서는 sql문 및 결과 출력 -->
<!-- SQL문과 소요된 시간 -->
<logger name="jdbc.sqltiming" level="DEBUG" />
<!-- SQL 결과 조회된 데이터를 table 형식으로 출력 -->
<logger name="jdbc.resultsettable" level="DEBUG" />
</springProfile>
<!-- SQL문 출력 -->
<logger name="jdbc.sqlonly" level="OFF"/>
<!-- result를 포함한 모든 JDBC 호출 정보 -->
<logger name="jdbc.resultset" level="OFF"/>
<!-- DB connection open/close -->
<logger name="jdbc.connection" level="OFF"/>
<!-- resultset을 제외한 JDBC 호출 정보 -->
<logger name="jdbc.audit" level="OFF"/>
<logger name="org.mariadb.jdbc" level="ERROR"/>
<!-- DB Connection Pool 관련 -->
<logger name="com.zaxxer.hikari.pool.PoolBase" level="ERROR" />
<logger name="com.zaxxer.hikari.pool.HikariPool" level="ERROR" />
<logger name="com.zaxxer.hikari.HikariDataSource" level="ERROR" />
<!-- ************************************************************************* -->
<!-- SQL log -->
<!-- ************************************************************************* -->
<!-- ************************************************************************* -->
<!-- spring / 3rdparty log : root appender로 로그 전파 - additivity="true" -->
<!-- ************************************************************************* -->
<logger name="io.swagger.v3.core.converter" level="INFO"/>
<logger name="org.egovframe.rte.fdl.cmmn.exception.manager" level="INFO"/>
<logger name="org.egovframe.rte.fdl.cmmn.aspect.ExceptionTransfer" level="INFO"/>
<logger name="org.egovframe" level="ERROR"/>
<logger name="org.apache.commons" level="INFO"/>
<logger name="com.zaxxer.hikari.pool.HikariPool" level="INFO"/>
<!-- ************************************************************************* -->
<!-- spring / 3rdparty log -->
<!-- ************************************************************************* -->
<!-- ************************************************************************* -->
<!-- application log : root appender로 로그 전파 - additivity="true" -->
<!-- ************************************************************************* -->
<!-- <logger name="org.springframework.web.filter.MustRequestLoggingFilter" level="DEBUG" additivity="false"/>-->
<!--logger name="kr.xit.core.filter.CustomRequestLoggingFilter" level="DEBUG"/-->
<logger name="kr.xit" level="DEBUG"/>
<!-- ************************************************************************* -->
<!-- application log -->
<!-- ************************************************************************* -->
<!-- ************************************************************************* -->
<!-- root logging -->
<!-- ************************************************************************* -->
<root level="DEBUG">
<springProfile name="prod">
<appender-ref ref="ASYNC_ROLLING"/>
</springProfile>
<springProfile name="local, dev">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_ROLLING"/>
</springProfile>
</root>
</configuration>

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Title</title>
</head>
<body>
<p>Error</p>
</body>
</html>

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>전자고지 API Framework</title>
</head>
<body>
<h3>전자고지 API Framework</h3>
<p>
<a href="http://localhost:8081/swagger-ui.html">API Document</a>
</p>
<p>
자세한 사항은 README.md 참고
</p>
</body>
</html>

@ -43,7 +43,7 @@ spring:
# core의 application-common.yml과 application-auth.yml include # core의 application-common.yml과 application-auth.yml include
include: include:
- https #- https
- common - common
- auth - auth
- app - app

@ -3,21 +3,6 @@
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
app: app:
# spring security 사용여부
spring:
security:
white-list:
/,
/login/**,
/api/**,
/batch/**,
/auth/login-jwt,
/auth/login,
/api-docs/**,
/swagger-resources,
/swagger-ui.html,
/swagger-ui/**
# 암호화 알고리즘 # 암호화 알고리즘
encrypt: encrypt:
alg: SHA-256 alg: SHA-256

@ -15,6 +15,7 @@
<module>mens-core</module> <module>mens-core</module>
<module>mens-api</module> <module>mens-api</module>
<module>mens-batch</module> <module>mens-batch</module>
<module>mens-admin</module>
</modules> </modules>
<properties> <properties>

Loading…
Cancel
Save