어드민 vuejs 통합 빌드 환경 구성 / 유플러스 마스킹 유틸 구성

This commit is contained in:
hyunjin35
2022-06-07 16:56:26 +09:00
parent bb8850ae9c
commit b6d9091838
14 changed files with 488 additions and 303 deletions

View File

@@ -50,6 +50,10 @@ dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security'
// RestTemplate 대신 WebClient 사용 // RestTemplate 대신 WebClient 사용
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux'
// validation
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation'
// vuejs 파일 index 지정
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
// JSP 사용시 // JSP 사용시
// implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper' // implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper'
// implementation group: 'javax.servlet', name: 'jstl', version: '1.2' // implementation group: 'javax.servlet', name: 'jstl', version: '1.2'
@@ -96,18 +100,6 @@ dependencies {
// custom libs // custom libs
implementation fileTree(dir:'libs', include:'*.jar') implementation fileTree(dir:'libs', include:'*.jar')
// mysql 사용시
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
implementation 'mysql:mysql-connector-java'
//implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.22'
//implementation group: 'mysql', name: 'mysql-connector-java', version: '5.1.47'
// https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp
implementation group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'
// validation
implementation 'org.springframework.boot:spring-boot-starter-validation'
} }
bootJar { bootJar {

View File

@@ -1,4 +1 @@
rootProject.name = 'hubeasy-admin' rootProject.name = 'hubez-admin'
// include ':cm-web-common'
// project(':cm-web-common').projectDir = new File(settingsDir, '../cm-web-common')

View File

@@ -1,15 +1,14 @@
package kr.co.uplus.ez; package kr.co.uplus.ez;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component @Component
public class Scheduler { public class Scheduler {
private static final Logger log = LoggerFactory.getLogger(Scheduler.class);
/** /**
* 스케줄러 트리거는 해당영역에 선언 / 서비스영역은 별도 * 스케줄러 트리거는 해당영역에 선언 / 서비스영역은 별도
*/ */

View File

@@ -3,19 +3,18 @@ package kr.co.uplus.ez;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.AbstractEnvironment;
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) import kr.co.uplus.ez.common.utils.USecuritySupUtils;
public class WebApplication extends SpringBootServletInitializer { import lombok.extern.slf4j.Slf4j;
private static final Logger log = LoggerFactory.getLogger(WebApplication.class); @Slf4j
@SpringBootApplication
public class WebApplication extends SpringBootServletInitializer {
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
@@ -32,6 +31,9 @@ public class WebApplication extends SpringBootServletInitializer {
@PostConstruct @PostConstruct
public void onStartup() { public void onStartup() {
// 유플러스 마스킹 유틸 적용
USecuritySupUtils.initMaskingRule();
Thread checkThread = new Thread(new CheckProcess()); Thread checkThread = new Thread(new CheckProcess());
checkThread.setDaemon(true); checkThread.setDaemon(true);
checkThread.start(); checkThread.start();
@@ -44,10 +46,13 @@ public class WebApplication extends SpringBootServletInitializer {
} }
} }
/**
* 프로세스 hang 확인을 위한 1분마다 메모리 로깅 기능
* 데몬 스레드 방식으로 스프링 관리 스레드 아님
*/
@Slf4j
class CheckProcess implements Runnable { class CheckProcess implements Runnable {
private static final Logger log = LoggerFactory.getLogger(CheckProcess.class);
private static final String PROC_NAME = "mhez-admin"; private static final String PROC_NAME = "mhez-admin";
@Override @Override
public void run() { public void run() {

View File

@@ -1,8 +1,5 @@
package kr.co.uplus.ez.common.jwt; package kr.co.uplus.ez.common.jwt;
import static kr.co.uplus.ez.config.SecurityConfig.LOGIN_API_URL;
import static kr.co.uplus.ez.config.SecurityConfig.PUBLIC_API_URL;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
@@ -26,30 +23,21 @@ public abstract class JwtAuthFilter extends OncePerRequestFilter {
protected final JwtProperties jwtProps; protected final JwtProperties jwtProps;
public JwtAuthFilter(JwtProperties jwtProps) { public JwtAuthFilter(JwtProperties jwtProps) {
this.jwtProps = jwtProps; this.jwtProps = jwtProps;
} }
public abstract String getToken(HttpServletRequest request); public abstract String getToken(HttpServletRequest request);
public abstract void onValidateSuccess(HttpServletRequest request, HttpServletResponse response, Claims claims); public abstract void onValidateSuccess(HttpServletRequest request, HttpServletResponse response, Claims claims);
public abstract void onValidateException(HttpServletRequest request, HttpServletResponse response, JwtException exception);
public abstract void onValidateException(HttpServletRequest request, HttpServletResponse response,
JwtException exception);
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException { throws ServletException, IOException {
if (WebUtils.isResourceRequest(request) || WebUtils.isMatchedUriPattern(request, "/login", if (WebUtils.isResourceRequest(request) || WebUtils.isMatchedUriPattern(request, "/api/v1/bo/login/**")) {
"/api/v1/bo/login/**",
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/v3/api-docs/**",
"/swagger-ui/**",
"/")) {
chain.doFilter(request, response); chain.doFilter(request, response);
return; return;
} }
@@ -67,9 +55,7 @@ public abstract class JwtAuthFilter extends OncePerRequestFilter {
try { try {
// 4. 토큰 검증 // 4. 토큰 검증
claims = Jwts.parser() claims = Jwts.parser().setSigningKey(TextCodec.BASE64.decode(jwtProps.getKeyString())).parseClaimsJws(token)
.setSigningKey(TextCodec.BASE64.decode(jwtProps.getKeyString()))
.parseClaimsJws(token)
.getBody(); .getBody();
String subject = claims.getSubject(); String subject = claims.getSubject();
@@ -80,13 +66,13 @@ public abstract class JwtAuthFilter extends OncePerRequestFilter {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> principalMap = (Map<String, Object>) claims.get("principal"); Map<String, Object> principalMap = (Map<String, Object>) claims.get("principal");
JwtUser user = JwtUser.createAuthUser(principalMap); JwtUser user = JwtUser.createAuthUser(principalMap);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null,
user.getAuthorities());
// 6. 사용자 인증 처리 (Now, user is authenticated) // 6. 사용자 인증 처리 (Now, user is authenticated)
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
} }
} } catch (JwtException e) {
catch(JwtException e) {
onValidateException(request, response, e); onValidateException(request, response, e);
throw e; throw e;
} }

View File

@@ -0,0 +1,251 @@
package kr.co.uplus.ez.common.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;
import lguplus.security.data.USecurityModule;
import lguplus.security.json.simple.parser.ParseException;
import lguplus.security.vulner.SetPolicyFile;
public class USecuritySupUtils {
private static final String RULE_NM = "UplusMR";
private static final String RULE_FILE_NAME = "UplusMaskingRule";
private static final String RULE_FILE_SUFFIX = "json";
/**
* 마스킹룰 JSON 파일 위치를 재지정 하기 위한 기능
* USecuritySupUtils.initMaskingRule()
*/
public static void initMaskingRule() {
try {
ClassPathResource resource = new ClassPathResource(RULE_FILE_NAME + "." + RULE_FILE_SUFFIX);
InputStream inputStream = resource.getInputStream();
File tmpFile = File.createTempFile(RULE_FILE_NAME, RULE_FILE_SUFFIX);
FileUtils.copyInputStreamToFile(inputStream, tmpFile);
SetPolicyFile.setRuleFile(RULE_NM, tmpFile.getPath());
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
/**
* 카드정보
*
* 앞3자리, 뒤4자리 남긴 후 마스킹
* 단, 7자리 이하는 앞 3자리 남기고 마스킹
* 3자리 이하는 모두 마스킹
* ex) 123*-****-****-1234
* USecuritySupUtils.maskingCardnum("1234-1234-1234-1234")
*
* @param value
* @return
*/
public static String maskingCardnum(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "cardnum", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 전화번호
*
* 국번 3자리 혹은 4자리 마스킹
* 단, 8자리 이하는 뒤 4자리 남기고 마스킹
* 4자리 이하는 모두 마스킹
* ex) 02-****-1234 / 010-****-1234
* USecuritySupUtils.maskingPhone("02-1234-1234")
* USecuritySupUtils.maskingPhone("010-1234-1234")
*
* @param value
* @return
*/
public static String maskingPhone(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "phone", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 시리얼번호
*
* 뒤 4자리 외 마스킹
* 단, 4자리 이하는 모두 마스킹
* ex) ***4567
* USecuritySupUtils.maskingSerial("12345678")
*
* @param value
* @return
*/
public static String maskingSerial(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "serial", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 계좌번호
*
* 앞 3자리, 뒤 4자리 남긴 후 마스킹
* 단, 7자리 이하는 앞 3자리 남기고 마스킹
* 3자리 이하는 모두 마스킹
* ex) 123-***-**3456
* USecuritySupUtils.maskingAccountnum("123-123-123456")
*
* @param value
* @return
*/
public static String maskingAccountnum(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "accountnum", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* IP
*
* ipv4: Dot 기준으로 3번째 블록 마스킹
* ex) 123.123.***.123
* USecuritySupUtils.maskingIp("123.123.123.123")
* ipv6: Colon 기준으로 마지막 블록 마스킹
* ex) 2001:0DB8:0:0:0:0:1428:****
* USecuritySupUtils.maskingIp("2001:0DB8:0:0:0:0:1428:1234")
*
* @param value
* @return
*/
public static String maskingIp(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "ip", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 이름
*
* 성 뒤 이름의 첫자리 마스킹
* ex) 홍*동, 허*설헌
* USecuritySupUtils.maskingName("홍길동")
*
* @param value
* @return
*/
public static String maskingName(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "name", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 주민번호
*
* 뒤 6자리 마스킹
* ex) 800101-1******
* USecuritySupUtils.maskingJumin("800101-1234567")
*
* @param value
* @return
*/
public static String maskingJumin(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "jumin", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 이메일주소
*
* 계정 앞 3자리 외 마스킹
* 단, 3자리 이하는 계정 모두 마스킹
* ex) abc*****@hanmail.net
* USecuritySupUtils.maskingEmail("abcdefg@hanmail.net")
*
* @param value
* @return
*/
public static String maskingEmail(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "email", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
/**
* 주소
*
* 도로명 뒤 마스킹(단 병기되는 동은 표시가능) 읍,면,동,리 이후 마스킹 또는 상세주소 제외
* 단, 마스킹 대상이 없을 경우 (주소입력오류)
* 1) 1차로 숫자만 마스킹
* 2) 숫자도 없을 경우 뒤에서 3자리 마스킹
* ex) 서울시 마포구 월드컵북로 ***
* ex) 서울 영등포구 여의도동 **-*
* USecuritySupUtils.maskingAddress("서울시 마포구 월드컵북로 200-1")
*
* @param value
* @return
*/
public static String maskingAddress(String value) {
String v = "";
if (StringUtils.hasText(value)) {
try {
v = USecurityModule.maskingApply(RULE_NM, "address", value);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return v;
}
}

View File

@@ -20,7 +20,6 @@ import org.springframework.web.cors.CorsUtils;
import kr.co.uplus.ez.api.login.LoginFailureHandler; import kr.co.uplus.ez.api.login.LoginFailureHandler;
import kr.co.uplus.ez.api.login.LoginSuccessHandler; import kr.co.uplus.ez.api.login.LoginSuccessHandler;
import kr.co.uplus.ez.common.data.ConfigProps;
import kr.co.uplus.ez.common.jwt.JwtAuthCookieFilter; import kr.co.uplus.ez.common.jwt.JwtAuthCookieFilter;
import kr.co.uplus.ez.common.jwt.JwtAuthHeaderFilter; import kr.co.uplus.ez.common.jwt.JwtAuthHeaderFilter;
import kr.co.uplus.ez.common.jwt.JwtExceptionFilter; import kr.co.uplus.ez.common.jwt.JwtExceptionFilter;
@@ -31,7 +30,7 @@ import kr.co.uplus.ez.config.filter.VueStaticFilter;
@EnableWebSecurity @EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter { public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String LOGIN_FORM_URL = "/login/**"; private static final String LOGIN_FORM_URL = "/login";
public static final String LOGIN_API_URL = "/api/v1/bo/login"; public static final String LOGIN_API_URL = "/api/v1/bo/login";
public static final String LOGIN_FAIL_URL = "/login?error=true"; public static final String LOGIN_FAIL_URL = "/login?error=true";
public static final String LOGIN_SUCC_URL = "/"; public static final String LOGIN_SUCC_URL = "/";
@@ -43,19 +42,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String[] PERMIT_URL_ARRAY = { private static final String[] PERMIT_URL_ARRAY = {
"/login", "/login",
"/api/v1/bo/login/**", "/api/v1/bo/login/**",
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/v3/api-docs/**",
"/swagger-ui/**", "/swagger-ui/**",
"/swagger-resources/**",
"/v3/api-docs",
"/v3/api-docs/**",
"/" "/"
}; };
private static final String[] AUTH_URL_ARRAY = { private static final String[] AUTH_URL_ARRAY = {
"/api/v1/bo/login/*", "/api/v1/bo/login/*",
"/api/v1/bo/comm/**", "/api/v1/bo/comm/**",
@@ -75,16 +68,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private UserDetailsService userDetailsService; private UserDetailsService userDetailsService;
@Autowired
private ConfigProps cprops;
@Autowired @Autowired
private JwtProperties jwtProps; private JwtProperties jwtProps;
// @Autowired
// private AuthService authService;
@Override @Override
public void configure(WebSecurity web) throws Exception { public void configure(WebSecurity web) throws Exception {
web.ignoring() web.ignoring()
@@ -100,7 +86,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) throws Exception { public void configure(HttpSecurity http) throws Exception {
http http
.addFilterBefore(new VueStaticFilter(), UsernamePasswordAuthenticationFilter.class) // Vue에서 호출시 화면관련 URL은 / forward .addFilterBefore(new VueStaticFilter(), UsernamePasswordAuthenticationFilter.class) // Vue에서 호출시 화면관련 URL은 / forward
// .addFilterBefore(new XssFilter(cprops), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtExceptionFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JwtExceptionFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtAuthHeaderFilter(jwtProps), UsernamePasswordAuthenticationFilter.class); .addFilterBefore(new JwtAuthHeaderFilter(jwtProps), UsernamePasswordAuthenticationFilter.class);

View File

@@ -2,8 +2,6 @@ package kr.co.uplus.ez.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.PathSelectors;
@@ -15,20 +13,12 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration @Configuration
@EnableSwagger2 @EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport { public class SwaggerConfig {
private static final String API_TITLE = "HubEasy Admin"; private static final String API_TITLE = "mhez-admin";
private static final String API_DESC = "허브이지 어드민에서 사용되는 API 문서입니다."; private static final String API_DESC = "U+메시지허브이지 어드민에서 사용되는 API 문서입니다.";
private static final String API_VER = "1.0"; private static final String API_VER = "1.0";
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
@Bean @Bean
public Docket api() { public Docket api() {
return new Docket(DocumentationType.OAS_30).useDefaultResponseMessages(false).select() return new Docket(DocumentationType.OAS_30).useDefaultResponseMessages(false).select()

View File

@@ -0,0 +1,22 @@
package kr.co.uplus.ez.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* swagger 및 정적파일 경로 지정
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}

View File

@@ -1,6 +1,7 @@
package kr.co.uplus.ez.config.filter; package kr.co.uplus.ez.config.filter;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@@ -10,33 +11,32 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.filter.GenericFilterBean;
// http://www.servletsuite.com/servlets/xssflt.htm
public class VueStaticFilter extends GenericFilterBean { public class VueStaticFilter extends GenericFilterBean {
// Vuejs router url prefix 선언
private static final String[] FRONTEND_URLS = { "/view", "/custMgt", "/sysMgt", "/attractMgt", "/servMgt",
"/calculate", "/channelMgt", "/sendNumMgt", "/mntrng", "/riskMgt", "/stats" };
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException { throws IOException, ServletException {
if (shouldExclude(request)) { if (shouldExclude(request)) {
chain.doFilter(request, response); chain.doFilter(request, response);
// some logic so the request doesnt go to the servlet
// maybe you could just forward
// the request directly to the file getting accessed. not sure if that would
// work
} else { } else {
// vuejs에 해당하는 페이지는 index를 바라보도록 전달
((HttpServletRequest) request).getRequestDispatcher("/").forward(request, response); ((HttpServletRequest) request).getRequestDispatcher("/").forward(request, response);
} }
// file should be passed to the servlet; you can do some logic here
// if you want
} }
private boolean shouldExclude(ServletRequest req) { private boolean shouldExclude(ServletRequest req) {
boolean isEx = true;
if (req instanceof HttpServletRequest) { if (req instanceof HttpServletRequest) {
HttpServletRequest hreq = (HttpServletRequest) req; HttpServletRequest hreq = (HttpServletRequest) req;
return !(hreq.getRequestURI().startsWith("/view")); if (Arrays.stream(FRONTEND_URLS).anyMatch(s -> hreq.getRequestURI().startsWith(s))) {
return false;
} }
return true; }
return isEx;
} }
} }

View File

@@ -0,0 +1,150 @@
package kr.co.uplus.ez.view.main;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ApiResponseMessage;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class MainViewController {
// Vue일 경우 index로 전달
@GetMapping("/")
public String home() {
return "index";
}
/*
* 엑셀 업로드 poi 4.1 사용 테스트 x
*/
@PostMapping("/insertFileXcel")
@ResponseBody
public ApiResponseMessage<?> insertFileXcel(MultipartHttpServletRequest multipartRequest) {
MultipartFile file = multipartRequest.getFile("file");
String colName = multipartRequest.getParameter("colName");
ApiResponseMessage result = new ApiResponseMessage(ApiResponseCode.SUCCESS);
try {
int rowindex = 0;
int columnindex = 0;
InputStream in = file.getInputStream();
@SuppressWarnings("resource")
XSSFWorkbook workbook = new XSSFWorkbook(in);
XSSFSheet sheet = workbook.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
if (rows > 10000 || rows < 1) {
// 엑셀 로우 건수가 10000건이 넘으면 false 반환
result.setData(false);
} else {
HashMap<String, String> xcelData = new HashMap<String, String>();
for (rowindex = 0; rowindex < rows; rowindex++) {
XSSFRow row = sheet.getRow(rowindex);
if (row != null) {
int cells = row.getPhysicalNumberOfCells();
for (columnindex = 0; columnindex <= cells - 1; columnindex++) {
// 셀값을 읽는다
XSSFCell cell = row.getCell(columnindex);
String value = "";
if (cell == null) {
continue;
} else {
// 타입별로 내용 읽기
switch (cell.getCellType()) {
case FORMULA:
value = cell.getCellFormula();
break;
case NUMERIC:
value = cell.getNumericCellValue() + "";
break;
case STRING:
value = cell.getStringCellValue() + "";
break;
case BLANK:
value = cell.getBooleanCellValue() + "";
break;
}
}
if ("false".equals(value)) {
// logger.info(rowindex+"번 행 Error :" +value);
break;
} else {
// logger.info(rowindex+"번 행 : "+columnindex+"번 열 값은: "+value);
// xcelData.put(value, value)
}
}
}
XSSFCell cell = row.getCell(columnindex);
}
result.setData(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.info("data : {}", result);
return result;
}
/*
* 엑셀 업로드 poi 3.13 사용 rcs에서 테스트 완료
*/
/*
* @PostMapping("/insertFileXcel")
*
* @ResponseBody public Result<?> insertFileXcel(MultipartHttpServletRequest
* multipartRequest){
*
* MultipartFile file = multipartRequest.getFile("file"); String colName =
* multipartRequest.getParameter("colName"); Result<Map<String,Object>> result =
* new Result<>();
*
* try { int rowindex=0; int columnindex=0;
*
* InputStream in = file.getInputStream();
*
* @SuppressWarnings("resource") XSSFWorkbook workbook = new XSSFWorkbook(in);
* XSSFSheet sheet=workbook.getSheetAt(0);
*
* int rows=sheet.getPhysicalNumberOfRows(); // 엑셀 갯수 if(rows > 100 || rows < 1)
* { result.setSuccess(false); }else { HashMap<String, String> xcelData = new
* HashMap<String, String>(); for(rowindex=0;rowindex<rows;rowindex++){ XSSFRow
* row=sheet.getRow(rowindex); if(row !=null) { int
* cells=row.getPhysicalNumberOfCells(); for(columnindex=0;
* columnindex<=cells-1; columnindex++){ //셀값을 읽는다 XSSFCell
* cell=row.getCell(columnindex); String value="";
*
* if(cell==null){ continue; }else{ //타입별로 내용 읽기 switch (cell.getCellType()){
* case XSSFCell.CELL_TYPE_FORMULA: value=cell.getCellFormula(); break; case
* XSSFCell.CELL_TYPE_NUMERIC: value=cell.getNumericCellValue()+""; break; case
* XSSFCell.CELL_TYPE_STRING: value=cell.getStringCellValue()+""; break; case
* XSSFCell.CELL_TYPE_BLANK: value=cell.getBooleanCellValue()+""; 7 break; } }
* if("false".equals(value)) { logger.info(rowindex+"번 행 Error :" +value);
*
* break; }else { logger.info(rowindex+"번 행 : "+columnindex+"번 열 값은: "+value);
* // xcelData.put(value, value) } } } XSSFCell cell=row.getCell(columnindex); }
* result.setSuccess(true); } } catch (IOException e) { // TODO Auto-generated
* catch block e.printStackTrace(); } return result; }
*/
}

View File

@@ -1,197 +0,0 @@
package kr.co.uplus.ez.view.sample;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ApiResponseMessage;
@Controller
public class MainViewController {
private final Logger logger = LoggerFactory.getLogger(getClass());
// WEB 없이 구성될 경우 필요
// Vue일 경우 index로 전달
@GetMapping("/")
public String home() {
return "index";
}
// Vue일 경우 index로 전달
@RequestMapping(value = "/{path:[^\\.]*}")
public String redirect() {
return "forward:/";
}
/*
* 엑셀 업로드
* poi 4.1 사용 테스트 x
* */
@PostMapping("/insertFileXcel")
@ResponseBody
public ApiResponseMessage<?> insertFileXcel(MultipartHttpServletRequest multipartRequest){
MultipartFile file = multipartRequest.getFile("file");
String colName = multipartRequest.getParameter("colName");
ApiResponseMessage result = new ApiResponseMessage(ApiResponseCode.SUCCESS);
try {
int rowindex=0;
int columnindex=0;
InputStream in = file.getInputStream();
@SuppressWarnings("resource")
XSSFWorkbook workbook = new XSSFWorkbook(in);
XSSFSheet sheet=workbook.getSheetAt(0);
int rows=sheet.getPhysicalNumberOfRows();
if(rows > 10000 || rows < 1) {
// 엑셀 로우 건수가 10000건이 넘으면 false 반환
result.setData(false);
}else {
HashMap<String, String> xcelData = new HashMap<String, String>();
for(rowindex=0;rowindex<rows;rowindex++){
XSSFRow row=sheet.getRow(rowindex);
if(row !=null) {
int cells=row.getPhysicalNumberOfCells();
for(columnindex=0; columnindex<=cells-1; columnindex++){
//셀값을 읽는다
XSSFCell cell = row.getCell(columnindex);
String value="";
if(cell==null){
continue;
}else{
//타입별로 내용 읽기
switch (cell.getCellType()){
case FORMULA:
value=cell.getCellFormula();
break;
case NUMERIC:
value=cell.getNumericCellValue()+"";
break;
case STRING:
value=cell.getStringCellValue()+"";
break;
case BLANK:
value=cell.getBooleanCellValue()+"";
break;
}
}
if("false".equals(value)) {
// logger.info(rowindex+"번 행 Error :" +value);
break;
}else {
// logger.info(rowindex+"번 행 : "+columnindex+"번 열 값은: "+value);
// xcelData.put(value, value)
}
}
}
XSSFCell cell=row.getCell(columnindex);
}
result.setData(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("data : {}", result);
return result;
}
/*
* 엑셀 업로드
* poi 3.13 사용 rcs에서 테스트 완료
* */
/*
@PostMapping("/insertFileXcel")
@ResponseBody
public Result<?> insertFileXcel(MultipartHttpServletRequest multipartRequest){
MultipartFile file = multipartRequest.getFile("file");
String colName = multipartRequest.getParameter("colName");
Result<Map<String,Object>> result = new Result<>();
try {
int rowindex=0;
int columnindex=0;
InputStream in = file.getInputStream();
@SuppressWarnings("resource")
XSSFWorkbook workbook = new XSSFWorkbook(in);
XSSFSheet sheet=workbook.getSheetAt(0);
int rows=sheet.getPhysicalNumberOfRows();
// 엑셀 갯수
if(rows > 100 || rows < 1) {
result.setSuccess(false);
}else {
HashMap<String, String> xcelData = new HashMap<String, String>();
for(rowindex=0;rowindex<rows;rowindex++){
XSSFRow row=sheet.getRow(rowindex);
if(row !=null) {
int cells=row.getPhysicalNumberOfCells();
for(columnindex=0; columnindex<=cells-1; columnindex++){
//셀값을 읽는다
XSSFCell cell=row.getCell(columnindex);
String value="";
if(cell==null){
continue;
}else{
//타입별로 내용 읽기
switch (cell.getCellType()){
case XSSFCell.CELL_TYPE_FORMULA:
value=cell.getCellFormula();
break;
case XSSFCell.CELL_TYPE_NUMERIC:
value=cell.getNumericCellValue()+"";
break;
case XSSFCell.CELL_TYPE_STRING:
value=cell.getStringCellValue()+"";
break;
case XSSFCell.CELL_TYPE_BLANK:
value=cell.getBooleanCellValue()+"";
7 break;
}
}
if("false".equals(value)) {
logger.info(rowindex+"번 행 Error :" +value);
break;
}else {
logger.info(rowindex+"번 행 : "+columnindex+"번 열 값은: "+value);
// xcelData.put(value, value)
}
}
}
XSSFCell cell=row.getCell(columnindex);
}
result.setSuccess(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
*/
}

View File

@@ -0,0 +1,11 @@
{
"jumin":"8,13",
"name":"2,2",
"cardnum":"reserved",
"accountnum":"reserved",
"phone":"reserved",
"address":"reserved",
"email":"reserved",
"serial":"reserved",
"ip":"reserved"
}

View File

@@ -12,12 +12,6 @@ spring:
max-request-size: 15MB max-request-size: 15MB
main: main:
banner-mode: log banner-mode: log
mvc:
# pathmatch:
# matching-strategy: ant_path_matcher
static-path-pattern: /static/**
view:
prefix: /templates/
app.props: app.props:
encKey: RW5jS2V5Rm9yVXBsdXM= encKey: RW5jS2V5Rm9yVXBsdXM=