diff --git a/mens-admin/.gitignore b/mens-admin/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/mens-admin/.gitignore @@ -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 \ No newline at end of file diff --git a/mens-admin/README.md b/mens-admin/README.md new file mode 100644 index 0000000..fdad075 --- /dev/null +++ b/mens-admin/README.md @@ -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 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) diff --git a/mens-admin/lib/ojdbc6.jar b/mens-admin/lib/ojdbc6.jar new file mode 100644 index 0000000..b663cd2 Binary files /dev/null and b/mens-admin/lib/ojdbc6.jar differ diff --git a/mens-admin/pom.xml b/mens-admin/pom.xml new file mode 100644 index 0000000..599b9e9 --- /dev/null +++ b/mens-admin/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + + kr.xit + mens-parent + 1.0.0 + + + mens-admin + 1.0.0 + war + mens-admin + Mobile Electronic Administrator Web + + + + kr.xit + mens-core + ${project.version} + + + + org.springframework.boot + spring-boot-starter-validation + + + org.apache.tomcat.embed + tomcat-embed-core + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-test + test + + + io.projectreactor + reactor-test + test + + + + org.projectlombok + lombok + ${lombok.version} + true + + + + com.oracle + ojdbc6 + 11.2.0.3 + system + ${basedir}/lib/ojdbc6.jar + + + + + + + install + ${basedir}/target + ${project.name} + + + src/main/resources + + * + static/**/* + egovframework/**/* + config/application.yml + config/application-app.yml + config/application-ens* + config/application-jpa.yml + config/application-${env}.yml + + true + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + jar-with-dependencies + + + + + false + + + + package + + single + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + kr.xit.EnsAdminApplication + + true + + + + + repackage + + + + + + + + diff --git a/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationEntryPoint.java b/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationEntryPoint.java new file mode 100644 index 0000000..b3de731 --- /dev/null +++ b/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationEntryPoint.java @@ -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)); + + } +} diff --git a/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationFilter.java b/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationFilter.java new file mode 100644 index 0000000..122001e --- /dev/null +++ b/mens-admin/src/main/java/egovframework/com/jwt/JwtAuthenticationFilter.java @@ -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); + + } +} diff --git a/mens-admin/src/main/java/egovframework/com/security/CustomAuthenticationPrincipalResolver.java b/mens-admin/src/main/java/egovframework/com/security/CustomAuthenticationPrincipalResolver.java new file mode 100644 index 0000000..64fe5e0 --- /dev/null +++ b/mens-admin/src/main/java/egovframework/com/security/CustomAuthenticationPrincipalResolver.java @@ -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(); + } +} diff --git a/mens-admin/src/main/java/egovframework/com/security/SecurityConfig.java b/mens-admin/src/main/java/egovframework/com/security/SecurityConfig.java new file mode 100644 index 0000000..8600748 --- /dev/null +++ b/mens-admin/src/main/java/egovframework/com/security/SecurityConfig.java @@ -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 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(); + } + +} diff --git a/mens-admin/src/main/java/kr/xit/EnsAdminApplication.java b/mens-admin/src/main/java/kr/xit/EnsAdminApplication.java new file mode 100644 index 0000000..9cadd2b --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/EnsAdminApplication.java @@ -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; + +/** + *
+ * 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       최초 생성
+ *
+ * 
+ */ +@Slf4j +@SpringBootApplication +@ConfigurationPropertiesScan(basePackages = {"egovframework", "kr.xit"}) +@ServletComponentScan +@ComponentScan( + nameGenerator = CustomBeanNameGenerator.class, + basePackages = {"egovframework", "kr.xit"} +) +public class EnsAdminApplication { + static final List 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("========================================================================================="); + } +} diff --git a/mens-admin/src/main/java/kr/xit/biz/auth/mapper/IAuthApiMapper.java b/mens-admin/src/main/java/kr/xit/biz/auth/mapper/IAuthApiMapper.java new file mode 100644 index 0000000..44271c8 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/biz/auth/mapper/IAuthApiMapper.java @@ -0,0 +1,27 @@ +package kr.xit.biz.auth.mapper; + +import egovframework.com.cmm.LoginVO; +import org.egovframe.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * description :
+ *
+ * packageName : kr.xit.biz.auth.mapper
+ * fileName    : IAuthApiMapper
+ * author      : limju
+ * date        : 2023-05-11
+ * ======================================================================
+ * 변경일         변경자        변경 내용
+ * ----------------------------------------------------------------------
+ * 2023-05-11    limju       최초 생성
+ *
+ * 
+ */ +@Mapper +public interface IAuthApiMapper { + LoginVO actionLogin(LoginVO vo); + // LoginVO searchId(LoginVO vo); + // LoginVO searchPassword(LoginVO vo); + // void updatePassword(LoginVO vo); +} diff --git a/mens-admin/src/main/java/kr/xit/biz/auth/service/AuthApiService.java b/mens-admin/src/main/java/kr/xit/biz/auth/service/AuthApiService.java new file mode 100644 index 0000000..7aa2388 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/biz/auth/service/AuthApiService.java @@ -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; + } +} diff --git a/mens-admin/src/main/java/kr/xit/biz/auth/service/IAuthApiService.java b/mens-admin/src/main/java/kr/xit/biz/auth/service/IAuthApiService.java new file mode 100644 index 0000000..5054481 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/biz/auth/service/IAuthApiService.java @@ -0,0 +1,32 @@ +package kr.xit.biz.auth.service; + +import egovframework.com.cmm.LoginVO; + +/** + * 일반 로그인을 처리하는 비즈니스 구현 클래스 + * @author 공통서비스 개발팀 박지욱 + * @since 2009.03.06 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자          수정내용
+ *  -------    --------    ---------------------------
+ *  2009.03.06  박지욱          최초 생성
+ *  2011.08.31  JJY            경량환경 템플릿 커스터마이징버전 생성
+ *
+ *  
+ */ +public interface IAuthApiService { + + /** + * 일반 로그인 처리 + * + * @param vo LoginVO + * @return LoginVO + */ + LoginVO actionLogin(LoginVO vo); + +} diff --git a/mens-admin/src/main/java/kr/xit/biz/auth/web/AuthApiController.java b/mens-admin/src/main/java/kr/xit/biz/auth/web/AuthApiController.java new file mode 100644 index 0000000..683601c --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/biz/auth/web/AuthApiController.java @@ -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; + +/** + *
+ * description : 인증 로그인 처리
+ *
+ * packageName : kr.xit.biz.auth
+ * fileName    : AuthApiController
+ * author      : limju
+ * date        : 2023-04-26
+ * ======================================================================
+ * 변경일         변경자        변경 내용
+ * ----------------------------------------------------------------------
+ * 2023-04-26    limju       최초 생성
+ *
+ * 
+ * @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 resultMap = new HashMap(); + + // 1. 일반 로그인 처리 + LoginVO loginResultVO = loginService.actionLogin(loginVO); + + if (loginResultVO != null && loginResultVO.getId() != null && !loginResultVO.getId().equals("")) { + + Map 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 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(); + } +} diff --git a/mens-admin/src/main/java/kr/xit/core/aop/TraceLoggerAspect.java b/mens-admin/src/main/java/kr/xit/core/aop/TraceLoggerAspect.java new file mode 100644 index 0000000..ce16461 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/core/aop/TraceLoggerAspect.java @@ -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; + +/** + *
+ * 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 객체 미사용에 따른 처리 추가
+ * 
+ * @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 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 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(); + } +} diff --git a/mens-admin/src/main/java/kr/xit/core/spring/config/SpringDocsApiConfig.java b/mens-admin/src/main/java/kr/xit/core/spring/config/SpringDocsApiConfig.java new file mode 100644 index 0000000..38e3fe3 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/core/spring/config/SpringDocsApiConfig.java @@ -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; + +/** + *
+ * description : Springdoc(swagger) 설정
+ *               설정내용이 상이한 경우 동일한 파일로 재정의 하거나 상속받아 사용
+ * packageName : kr.xit.core.spring.config
+ * fileName    : SpringDocsConfig
+ * author      : julim
+ * date        : 2023-04-28
+ * ======================================================================
+ * 변경일         변경자        변경 내용
+ * ----------------------------------------------------------------------
+ * 2023-04-28    julim       최초 생성
+ *
+ * 
+ */ +@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(); + } +} diff --git a/mens-admin/src/main/java/kr/xit/core/spring/util/AdminSpringUtils.java b/mens-admin/src/main/java/kr/xit/core/spring/util/AdminSpringUtils.java new file mode 100644 index 0000000..28220b6 --- /dev/null +++ b/mens-admin/src/main/java/kr/xit/core/spring/util/AdminSpringUtils.java @@ -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; + +/** + *
+ * 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       최초 생성
+ *
+ * 
+ * @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); +// } +} diff --git a/mens-admin/src/main/resources/config/application-app.yml b/mens-admin/src/main/resources/config/application-app.yml new file mode 100644 index 0000000..6d322e4 --- /dev/null +++ b/mens-admin/src/main/resources/config/application-app.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/application-dev.yml b/mens-admin/src/main/resources/config/application-dev.yml new file mode 100644 index 0000000..740b74c --- /dev/null +++ b/mens-admin/src/main/resources/config/application-dev.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/application-ens.yml b/mens-admin/src/main/resources/config/application-ens.yml new file mode 100644 index 0000000..f0a87e3 --- /dev/null +++ b/mens-admin/src/main/resources/config/application-ens.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/application-local.yml b/mens-admin/src/main/resources/config/application-local.yml new file mode 100644 index 0000000..b018e7b --- /dev/null +++ b/mens-admin/src/main/resources/config/application-local.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/application-prod.yml b/mens-admin/src/main/resources/config/application-prod.yml new file mode 100644 index 0000000..fc6764a --- /dev/null +++ b/mens-admin/src/main/resources/config/application-prod.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/application.yml b/mens-admin/src/main/resources/config/application.yml new file mode 100644 index 0000000..7b0c9b3 --- /dev/null +++ b/mens-admin/src/main/resources/config/application.yml @@ -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 diff --git a/mens-admin/src/main/resources/config/google_checks.xml b/mens-admin/src/main/resources/config/google_checks.xml new file mode 100644 index 0000000..1ca2848 --- /dev/null +++ b/mens-admin/src/main/resources/config/google_checks.xml @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mens-admin/src/main/resources/egovframework/mapper/biz/auth-mysql-mapper.xml b/mens-admin/src/main/resources/egovframework/mapper/biz/auth-mysql-mapper.xml new file mode 100644 index 0000000..2ef840f --- /dev/null +++ b/mens-admin/src/main/resources/egovframework/mapper/biz/auth-mysql-mapper.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/mens-admin/src/main/resources/egovframework/mapper/mapper-config.xml b/mens-admin/src/main/resources/egovframework/mapper/mapper-config.xml new file mode 100644 index 0000000..54a6663 --- /dev/null +++ b/mens-admin/src/main/resources/egovframework/mapper/mapper-config.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mens-admin/src/main/resources/egovframework/messages/message-admin.properties b/mens-admin/src/main/resources/egovframework/messages/message-admin.properties new file mode 100644 index 0000000..22457be --- /dev/null +++ b/mens-admin/src/main/resources/egovframework/messages/message-admin.properties @@ -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) + diff --git a/mens-admin/src/main/resources/egovframework/messages/message-admin_en.properties b/mens-admin/src/main/resources/egovframework/messages/message-admin_en.properties new file mode 100644 index 0000000..a646ced --- /dev/null +++ b/mens-admin/src/main/resources/egovframework/messages/message-admin_en.properties @@ -0,0 +1,3 @@ +#------------------------------------------------ +# Admin \uBA54\uC138\uC9C0 \uC815\uC758 +#------------------------------------------------ diff --git a/mens-admin/src/main/resources/egovframework/messages/message-admin_ko.properties b/mens-admin/src/main/resources/egovframework/messages/message-admin_ko.properties new file mode 100644 index 0000000..a646ced --- /dev/null +++ b/mens-admin/src/main/resources/egovframework/messages/message-admin_ko.properties @@ -0,0 +1,3 @@ +#------------------------------------------------ +# Admin \uBA54\uC138\uC9C0 \uC815\uC758 +#------------------------------------------------ diff --git a/mens-admin/src/main/resources/logback-spring.xml b/mens-admin/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..e5ae60d --- /dev/null +++ b/mens-admin/src/main/resources/logback-spring.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + ${CONSOLE_LOG_CHARSET} + + + + + + + + + ${LOG_PATH}/${LOG_FILE}.log + + DEBUG + ACCEPT + + ACCEPT + + + + + + ${FILE_LOG_PATTERN} + ${FILE_LOG_CHARSET} + + + + ${LOG_PATH}/backup/${LOG_FILE}_%d{yyyy-MM-dd}.%i.log.gz + + 30MB + + 50 + + + + + + + + + 2048 + 20 + + 6000 + + + true + + ${isIncludeCallerData} + + + DEBUG + + + + + + + + + + + \"juminId\"\s*:\s*\"(.*?)\" + \"recveJuminno\"\s*:\s*\"(.*?)\" + \"recevAddr\"\s*:\s*\"(.*?)\" + \"recevDetailAddr\"\s*:\s*\"(.*?)\" + %-5p [%d{ISO8601,UTC}] [%thread] %c: %m%n%rootException + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mens-admin/src/main/resources/static/error.html b/mens-admin/src/main/resources/static/error.html new file mode 100644 index 0000000..a49f913 --- /dev/null +++ b/mens-admin/src/main/resources/static/error.html @@ -0,0 +1,10 @@ + + + + + Title + + +

Error

+ + diff --git a/mens-admin/src/main/resources/static/index.html b/mens-admin/src/main/resources/static/index.html new file mode 100644 index 0000000..f6e2484 --- /dev/null +++ b/mens-admin/src/main/resources/static/index.html @@ -0,0 +1,16 @@ + + + + + 전자고지 API Framework + + +

전자고지 API Framework

+

+ API Document +

+

+ 자세한 사항은 README.md 참고 +

+ + diff --git a/mens-batch/src/main/resources/config/application.yml b/mens-batch/src/main/resources/config/application.yml index 5658d83..32c2f0f 100644 --- a/mens-batch/src/main/resources/config/application.yml +++ b/mens-batch/src/main/resources/config/application.yml @@ -43,7 +43,7 @@ spring: # core의 application-common.yml과 application-auth.yml include include: - - https + #- https - common - auth - app diff --git a/mens-core/src/main/resources/config/application-auth.yml b/mens-core/src/main/resources/config/application-auth.yml index 981227e..d086da6 100644 --- a/mens-core/src/main/resources/config/application-auth.yml +++ b/mens-core/src/main/resources/config/application-auth.yml @@ -3,21 +3,6 @@ #----------------------------------------------------------------------- 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: alg: SHA-256 diff --git a/pom.xml b/pom.xml index f155c37..7d3fa24 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ mens-core mens-api mens-batch + mens-admin