package kr.wisestone.owl.util;
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.google.common.collect.Lists;
|
import kr.wisestone.owl.constant.Regular;
|
import kr.wisestone.owl.domain.enumType.FileType;
|
import kr.wisestone.owl.type.LikeType;
|
import kr.wisestone.owl.vo.DepartmentVo;
|
import kr.wisestone.owl.vo.UserVo;
|
import org.apache.commons.codec.binary.*;
|
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
import org.apache.poi.ss.usermodel.Cell;
|
import org.jsoup.Jsoup;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.web.multipart.MultipartFile;
|
import org.w3c.dom.Document;
|
import org.w3c.dom.NodeList;
|
import org.xml.sax.InputSource;
|
import org.xml.sax.SAXException;
|
|
import javax.crypto.*;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.PBEKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import javax.net.ssl.HttpsURLConnection;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.ParserConfigurationException;
|
import java.io.*;
|
import java.math.BigInteger;
|
import java.net.*;
|
import java.nio.file.Files;
|
import java.nio.file.Paths;
|
import java.security.MessageDigest;
|
import java.security.spec.KeySpec;
|
import java.text.DecimalFormat;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import java.util.*;
|
import java.util.regex.Matcher;
|
import java.util.regex.Pattern;
|
|
public class CommonUtil {
|
private static final Logger LOGGER = LoggerFactory.getLogger(CommonUtil.class);
|
|
private static final String ENCODING_TYPE = "UTF-8";
|
private static final String SALT = "c7224df62de46817a515ce79b24d48d2"; // AES128 암호화에 사용
|
private static final String IV = "3c1bc71695361ca0aec4d83bb328b444"; // AES128 암호화에 사용
|
private static final String PASS_PHRASE = "1024"; // AES128 암호화에 사용
|
private static final int ITERATION_COUNT = 10000; // AES128 암호화에 사용
|
private static final int KEY_SIZE = 128; // AES128 암호화에 사용
|
private static final String TMP_UPLOAD_FOLDER = "/tmpUploadFolder/"; // 이슈 생성, 수정에서 파일 업로드할 때 임시 폴더로 사용'
|
public static final String COMMA = ","; // 구분자
|
|
|
public static String getClinetIp() {
|
try {
|
for (Enumeration<NetworkInterface> en = NetworkInterface
|
.getNetworkInterfaces(); en.hasMoreElements(); ) {
|
NetworkInterface intf = en.nextElement();
|
for (Enumeration<InetAddress> enumIpAddr = intf
|
.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
|
InetAddress inetAddress = enumIpAddr.nextElement();
|
if (!inetAddress.isLoopbackAddress()
|
&& !inetAddress.isLinkLocalAddress()
|
&& inetAddress.isSiteLocalAddress()) {
|
return inetAddress.getHostAddress().toString();
|
}
|
}
|
}
|
} catch (SocketException ex) {
|
|
}
|
return null;
|
}
|
|
/**
|
* 초기 패스워드를 생성하여 반환한다.
|
*
|
* @return
|
*/
|
|
public static String randomStringMaker() {
|
String random = null;
|
Integer length = 10;
|
random = RandomStringUtils.random(length, true, true);
|
|
return random;
|
}
|
|
public static String randomProjectKey() {
|
String random = null;
|
Integer length = 5;
|
random = RandomStringUtils.random(length, true, true).toUpperCase();
|
|
return random;
|
}
|
|
// sha 512 암호화
|
public static String encryptionSha512(String plainText) {
|
try {
|
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
byte[] messageDigest = md.digest(plainText.getBytes());
|
BigInteger no = new BigInteger(1, messageDigest);
|
String hashText = no.toString(16);
|
while (hashText.length() < 32) {
|
hashText = "0" + hashText;
|
}
|
return hashText;
|
} catch (Exception e) {
|
LOGGER.debug("encryptionSha512 error : " + e.getMessage());
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
public static String getServerIpAddress() {
|
try {
|
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
while (interfaces.hasMoreElements()) {
|
NetworkInterface networkInterface = interfaces.nextElement();
|
if (networkInterface.isLoopback() || !networkInterface.isUp() || networkInterface.isVirtual() || networkInterface.isPointToPoint()) {
|
continue;
|
}
|
|
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
|
while (addresses.hasMoreElements()) {
|
InetAddress inetAddress = addresses.nextElement();
|
|
final String ip = inetAddress.getHostAddress();
|
if (Inet4Address.class == inetAddress.getClass()) {
|
return ip;
|
}
|
}
|
}
|
} catch (SocketException e) {
|
throw new RuntimeException(e);
|
}
|
return null;
|
}
|
|
public static String likeStr(Map<String, Object> contents, String attr, LikeType type) {
|
if (contents == null) {
|
return "%%";
|
}
|
|
Object value = contents.get(attr);
|
if (value == null) {
|
return "%%";
|
}
|
return likeStr(value.toString(), type);
|
}
|
|
|
/**
|
* Query에서 사용되는 Like 문자열을 만든다.
|
*
|
* @param source
|
* @param type
|
* @return
|
*/
|
public static String likeStr(String source, LikeType type) {
|
if (source == null) {
|
return "%%";
|
}
|
else {
|
if (type == LikeType.FULL) {
|
return "%" + source + "%";
|
}
|
else if (type == LikeType.LEFT) {
|
return "%" + source;
|
}
|
else if (type == LikeType.RIGHT) {
|
return source + "%";
|
}
|
}
|
|
return source;
|
}
|
|
public static String nvl(Object obj) {
|
if (obj == null) {
|
return "";
|
}
|
return obj.toString();
|
}
|
|
public static String nvl(String message, String defaultStr) {
|
if (message == null) {
|
return defaultStr;
|
}
|
return message;
|
}
|
|
public static String getApprovalCode() {
|
return UUID.randomUUID().toString();
|
}
|
|
public static String getOnlyClassName(Object object) {
|
String className = object.getClass().getName();
|
|
String[] tokens = className.split("\\.");
|
int lastToken = tokens.length - 1;
|
String onlyName = tokens[lastToken];
|
|
return onlyName;
|
}
|
|
|
/**
|
* 연결 시스템의 xml 형식의 String 값을 파싱해서 url만 돌려준다.
|
*
|
* @param xml
|
* @return url String
|
*/
|
public static String xmltoString(String checkElementName, String xml) {
|
// TODO Auto-generated method stub
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilder db = null;
|
try {
|
db = dbf.newDocumentBuilder();
|
} catch (ParserConfigurationException e1) {
|
// TODO Auto-generated catch block
|
e1.printStackTrace();
|
}
|
Document doc = null;
|
NodeList nodes = null;
|
InputSource is = new InputSource();
|
is.setCharacterStream(new StringReader(xml));
|
try {
|
doc = db.parse(is);
|
} catch (SAXException e) {
|
// TODO Auto-generated catch block
|
e.printStackTrace();
|
} catch (IOException e) {
|
// TODO Auto-generated catch block
|
e.printStackTrace();
|
}
|
nodes = doc.getElementsByTagName(checkElementName);
|
|
return nodes.item(0).getTextContent();
|
}
|
|
public static long changeByteToMB(long size) {
|
return size / 1024 / 1024;
|
}
|
|
public static String getServerIp() {
|
try {
|
InetAddress address = InetAddress.getLocalHost();
|
return address.getHostAddress();
|
} catch (UnknownHostException e) {
|
e.printStackTrace();
|
}
|
|
return null;
|
}
|
|
/**
|
* 다국어 메시지를 반환한다.
|
*
|
* @return
|
*/
|
public static Map<String, String> getMessages() {
|
return getMessages(WebAppUtil.getHttpServletRequest().getServletContext().getRealPath("/"));
|
}
|
|
/**
|
* 다국어 메시지를 반환한다.
|
*
|
* @param rootPath
|
* @return
|
*/
|
public static Map<String, String> getMessages(String rootPath) {
|
Map<String, String> messages = new HashMap<String, String>();
|
|
String[] resources = new String[]{"messages.properties", "label.properties", "code.properties"};
|
for (String resource : resources) {
|
String resourcePath = rootPath + "/WEB-INF/i18n/" + resource;
|
LOGGER.debug("message path : resourcePath = " + resourcePath);
|
|
Properties prop = new Properties();
|
try {
|
prop.load(new FileInputStream(resourcePath));
|
Iterator iter = prop.keySet().iterator();
|
while (iter.hasNext()) {
|
String key = iter.next().toString();
|
messages.put(key, prop.get(key).toString());
|
}
|
} catch (FileNotFoundException e) {
|
e.printStackTrace();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
return messages;
|
}
|
|
public static String getDiagramObjectFormattedLocation(String location) {
|
if (location == null) {
|
return null;
|
}
|
|
if (location.indexOf(".") != -1) {
|
return location.substring(0, location.indexOf("."));
|
}
|
else {
|
return location;
|
}
|
}
|
|
public static String replaceBrWithNewline(String text) {
|
org.jsoup.nodes.Document document = Jsoup.parse(text);
|
document.select("br").append("\\n");
|
document.select("p").prepend("\\n\\n");
|
return document.text().replace("\\n", "\n");
|
}
|
|
// UUID 로 겹치지 않는 키를 만들어 낸다.
|
public static String getFileNameByUUID(String originalFileName) {
|
String fileName = UUID.randomUUID().toString();
|
String[] fileType = originalFileName.split("\\.");
|
|
fileName += "." + fileType[(fileType.length - 1)];
|
|
return fileName;
|
}
|
|
|
// multipartFile 정보를 file Map 형태로 변경한다.
|
public static Map<String, Object> makeFileMap(MultipartFile multipartFile) {
|
Map<String, Object> fileMap = new HashMap<>();
|
|
try {
|
fileMap.put("fileName", multipartFile.getOriginalFilename());
|
fileMap.put("fileSize", multipartFile.getSize());
|
fileMap.put("contentType", multipartFile.getContentType());
|
fileMap.put("file", CommonUtil.multipartToFile(multipartFile));
|
} catch (Exception e) {
|
LOGGER.debug(e.getMessage());
|
}
|
|
return fileMap;
|
}
|
|
// string file 정보를 file Map 형태로 변경한다.
|
public static Map<String, Object> makeFileMap(String fileName, String file, String contentType) {
|
Map<String, Object> fileMap = new HashMap<>();
|
|
try {
|
byte[] bytes = Base64.decodeBase64(file);
|
|
fileMap.put("fileName", fileName);
|
fileMap.put("fileSize", bytes.length);
|
fileMap.put("contentType", contentType);
|
fileMap.put("file", CommonUtil.bytesToFile(fileName, bytes));
|
} catch (Exception e) {
|
LOGGER.debug(e.getMessage());
|
}
|
|
return fileMap;
|
}
|
|
public static String getPostDataString(Map<String, String> params) throws UnsupportedEncodingException {
|
StringBuilder result = new StringBuilder();
|
boolean first = true;
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
if (first) {
|
first = false;
|
}
|
else {
|
result.append("&");
|
}
|
|
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
|
result.append("=");
|
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
|
}
|
|
return result.toString();
|
}
|
|
// multipart 파일을 File 로 변경
|
public static File multipartToFile(MultipartFile multipart) {
|
File convertFile = new File(WebAppUtil.getContextRealPath() + TMP_UPLOAD_FOLDER + getFileNameByUUID(multipart.getOriginalFilename()));
|
if (!convertFile.exists()) {
|
convertFile.mkdirs();
|
}
|
try {
|
multipart.transferTo(convertFile);
|
} catch (IllegalStateException | IOException e) {
|
LOGGER.debug("multipart 파일 file 변환 오류");
|
}
|
|
return convertFile;
|
}
|
|
// string을 파일로 변환
|
public static File stringToFile(String fileName, String file) {
|
|
byte[] bytes = null;
|
try {
|
bytes = Base64.decodeBase64(file);
|
|
} catch (Exception ex) {
|
LOGGER.debug("string to bytes 변환 오류");
|
}
|
|
if (bytes != null) {
|
return bytesToFile(fileName, bytes);
|
}
|
return null;
|
}
|
|
// bytes를 파일로 변환
|
public static File bytesToFile(String fileName, byte[] bytes) {
|
File convertFile = new File(WebAppUtil.getContextRealPath() + TMP_UPLOAD_FOLDER + getFileNameByUUID(fileName));
|
if (!convertFile.exists()) {
|
convertFile.mkdirs();
|
}
|
|
try{
|
FileOutputStream lFileOutputStream = new FileOutputStream(convertFile);
|
lFileOutputStream.write(bytes);
|
lFileOutputStream.close();
|
|
}catch (IllegalStateException | IOException e) {
|
LOGGER.debug("bytes 파일 file 변환 오류");
|
}
|
|
return convertFile;
|
}
|
|
public static InputStream getFileInputStream(String strPath, String strNewFileName){
|
InputStream objInputStream = null;
|
|
String strTargetPath = WebAppUtil.getContextRealPath() + strPath + "/" + strNewFileName;
|
|
File originFile = new File(strTargetPath);
|
|
try {
|
objInputStream = new FileInputStream(originFile);
|
} catch (Exception e) {
|
LOGGER.debug("get Inputstream Error : " + e.getMessage());
|
}
|
|
return objInputStream;
|
}
|
|
public static boolean moveToSaveStorage(String strBasePath, String strNewFileName, File tempFile) {
|
boolean bRet = false;
|
|
String strTargetBasePath = WebAppUtil.getContextRealPath() + strBasePath;
|
strTargetBasePath = Paths.get(strTargetBasePath).toString();
|
|
String strTargetPath = strTargetBasePath + "/" + strNewFileName;
|
|
File directory = new File(strTargetBasePath);
|
if (! directory.exists()){
|
try {
|
directory.mkdirs();
|
} catch (Exception e) {
|
LOGGER.debug("make directory error : " + e.getMessage());
|
}
|
}
|
|
bRet = tempFile.renameTo(new File(strTargetPath));
|
|
if( !bRet )
|
{
|
LOGGER.debug("file 이동 오류");
|
LOGGER.debug("original file Path : " + tempFile.getPath());
|
LOGGER.debug("target file Path : " + strTargetPath);
|
}
|
|
return bRet;
|
}
|
|
public static boolean deleteToSaveStorage(String strBasePath, String strFileName) {
|
boolean bRet = false;
|
String strTargetBasePath = WebAppUtil.getContextRealPath() + strBasePath;
|
String strTargetPath = strTargetBasePath + strFileName;
|
|
File delFile = new File(strTargetBasePath);
|
if ( delFile.exists()){
|
if(!delFile.isDirectory())
|
{
|
bRet = delFile.delete();
|
}
|
}
|
|
if( !bRet )
|
{
|
LOGGER.debug("file 삭제 오류");
|
LOGGER.debug("original file Path : " + strTargetPath);
|
}
|
|
return bRet;
|
}
|
|
// 파일 확장자 체크
|
// 1. 모든 확장자를 제한하고 허용하는 일부 확장자만 업로드 되도록 제한
|
// 2. 확장자는 뒤에서부터 체크한다.
|
// 3. 특수문자 체크
|
public static boolean checkFileType(String originalFileName) {
|
boolean permit = false;
|
|
if (StringUtils.isEmpty(originalFileName)) {
|
return permit;
|
}
|
|
String[] extFileTypes = {"hwp", "txt", "pptx", "ppt", "pdf", "xlsx", "xls", "docx", "doc", "jpg", "png", "gif", "jpeg", "tif", "bmp", "wmv", "avi", "mp4", "mkv", "mov", "zip"};
|
String fileName = originalFileName.toLowerCase();
|
int pos = fileName.lastIndexOf(".");
|
String ext = fileName.substring(pos + 1);
|
|
for (String extFileType : extFileTypes) {
|
if (extFileType.equals(ext)) {
|
permit = true;
|
break;
|
}
|
}
|
|
if (fileName.contains("%00") || fileName.contains("%zz") || fileName.contains(";")) {
|
permit = false;
|
}
|
|
return permit;
|
}
|
|
// 파일 유형을 찾는다.
|
public static FileType getFileType(String originalFileName) {
|
FileType fileType;
|
|
Map<String, Object> fileTypeMap = new HashMap<>();
|
fileTypeMap.put("hwp", FileType.DOC);
|
fileTypeMap.put("txt", FileType.DOC);
|
fileTypeMap.put("pptx", FileType.DOC);
|
fileTypeMap.put("ppt", FileType.DOC);
|
fileTypeMap.put("pdf", FileType.DOC);
|
fileTypeMap.put("xlsx", FileType.DOC);
|
fileTypeMap.put("xls", FileType.DOC);
|
fileTypeMap.put("docx", FileType.DOC);
|
fileTypeMap.put("doc", FileType.DOC);
|
// 문서 끝
|
fileTypeMap.put("jpg", FileType.IMAGE);
|
fileTypeMap.put("png", FileType.IMAGE);
|
fileTypeMap.put("gif", FileType.IMAGE);
|
fileTypeMap.put("jpeg", FileType.IMAGE);
|
fileTypeMap.put("tif", FileType.IMAGE);
|
fileTypeMap.put("bmp", FileType.IMAGE);
|
// 이미지 끝
|
fileTypeMap.put("wmv", FileType.MEDIA);
|
fileTypeMap.put("avi", FileType.MEDIA);
|
fileTypeMap.put("mp4", FileType.MEDIA);
|
fileTypeMap.put("mkv", FileType.MEDIA);
|
fileTypeMap.put("mov", FileType.MEDIA);
|
// 미디어 끝
|
|
String fileName = originalFileName.toLowerCase();
|
int pos = fileName.lastIndexOf(".");
|
String ext = fileName.substring(pos + 1);
|
|
if (fileTypeMap.get(ext) != null) {
|
fileType = (FileType) fileTypeMap.get(ext);
|
}
|
else {
|
fileType = FileType.ETC;
|
}
|
|
return fileType;
|
}
|
|
// 이름 마스킹 처리(성을 제외한 이름 마스킹 처리)
|
public static String maskingName(String name) {
|
String maskedName = ""; // 마스킹 이름
|
String firstName = ""; // 성
|
String lastName = ""; // 이름
|
int lastNameStartPoint; // 이름 시작 포인터
|
|
if (!StringUtils.isEmpty(name)) {
|
if (name.length() > 1) {
|
firstName = name.substring(0, 1);
|
lastNameStartPoint = name.indexOf(firstName);
|
lastName = name.substring(lastNameStartPoint + 1, name.length());
|
|
String makers = "";
|
|
for (int i = 0; i < lastName.length(); i++) {
|
makers += "*";
|
}
|
|
lastName = lastName.replace(lastName, makers);
|
maskedName = firstName + lastName;
|
}
|
else {
|
maskedName = "*";
|
}
|
}
|
|
return maskedName;
|
}
|
|
// AES 128 암호화
|
public static String encryptAES128(String plaintext) {
|
if (StringUtils.isEmpty(plaintext)) {
|
return null;
|
}
|
|
try {
|
SecretKey key = generateKey(SALT, PASS_PHRASE, ITERATION_COUNT, KEY_SIZE);
|
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, plaintext.getBytes("UTF-8"));
|
return encodeBase64(encrypted);
|
} catch (Exception e) {
|
LOGGER.debug("encryptAES128 error : " + e.getMessage());
|
}
|
|
return null;
|
}
|
|
private static String encodeBase64(byte[] bytes) {
|
return org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
|
}
|
|
private static SecretKey generateKey(String salt, String passPhrase, int iterationCount, int keySize) throws Exception {
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), decodeHex(salt), iterationCount, keySize);
|
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
|
return key;
|
}
|
|
private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) throws Exception {
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
cipher.init(encryptMode, key, new IvParameterSpec(decodeHex(iv)));
|
return cipher.doFinal(bytes);
|
}
|
|
private static byte[] decodeHex(String str) throws Exception {
|
return Hex.decodeHex(str.toCharArray());
|
}
|
|
// AES 128 복호화
|
public static String decryptAES128(String text) {
|
try {
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
KeySpec spec = new PBEKeySpec(PASS_PHRASE.toCharArray(), Hex.decodeHex(SALT.toCharArray()), ITERATION_COUNT, KEY_SIZE);
|
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(Hex.decodeHex(IV.toCharArray())));
|
byte[] decrypted = cipher.doFinal(Base64.decodeBase64(text));
|
return new String(decrypted, ENCODING_TYPE);
|
} catch (Exception e) {
|
LOGGER.debug("decryptAES128 error : " + e.getMessage());
|
}
|
|
return null;
|
}
|
|
// AES 256 암호화
|
/*public static String encryptAES256(String msg, String key) throws Exception {
|
SecureRandom random = new SecureRandom();
|
byte bytes[] = new byte[20];
|
random.nextBytes(bytes);
|
byte[] saltBytes = bytes;
|
// Password-Based Key Derivation function 2
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
// 70000번 해시하여 256 bit 길이의 키를 만든다.
|
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, 70000, 256);
|
SecretKey secretKey = factory.generateSecret(spec);
|
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
|
// 알고리즘/모드/패딩
|
// CBC : Cipher Block Chaining Mode
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
cipher.init(Cipher.ENCRYPT_MODE, secret);
|
AlgorithmParameters params = cipher.getParameters();
|
// Initial Vector(1단계 암호화 블록용)
|
byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
|
byte[] encryptedTextBytes = cipher.doFinal(msg.getBytes("UTF-8"));
|
byte[] buffer = new byte[saltBytes.length + ivBytes.length + encryptedTextBytes.length];
|
System.arraycopy(saltBytes, 0, buffer, 0, saltBytes.length);
|
System.arraycopy(ivBytes, 0, buffer, saltBytes.length, ivBytes.length);
|
System.arraycopy(encryptedTextBytes, 0, buffer, saltBytes.length + ivBytes.length, encryptedTextBytes.length);
|
return Base64.getEncoder().encodeToString(buffer);
|
}
|
|
// AES 256 복호화
|
public static String decryptAES256(String msg, String key) throws Exception {
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
ByteBuffer buffer = ByteBuffer.wrap(Base64.getDecoder().decode(msg));
|
byte[] saltBytes = new byte[20];
|
buffer.get(saltBytes, 0, saltBytes.length);
|
byte[] ivBytes = new byte[cipher.getBlockSize()];
|
buffer.get(ivBytes, 0, ivBytes.length);
|
byte[] encryoptedTextBytes = new byte[buffer.capacity() - saltBytes.length - ivBytes.length];
|
buffer.get(encryoptedTextBytes);
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, 70000, 256);
|
SecretKey secretKey = factory.generateSecret(spec);
|
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
|
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
|
byte[] decryptedTextBytes = cipher.doFinal(encryoptedTextBytes);
|
return new String(decryptedTextBytes);
|
}*/
|
|
// 엑셀 다운로드에 필요한 검색 조건 정보를 추출한다.
|
public static Map<String, Object> getSearchConditions(HttpServletRequest request) throws IOException {
|
Map<String, Object> conditions = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
|
Enumeration enumeration = request.getParameterNames();
|
while (enumeration.hasMoreElements()) {
|
String name = (String) enumeration.nextElement();
|
if (!org.springframework.util.StringUtils.isEmpty(request.getParameter(name))) {
|
params.put(name, request.getParameter(name));
|
}
|
}
|
|
if (!StringUtils.isEmpty(MapUtil.getString(params, "conditions"))) {
|
ObjectMapper mapper = new ObjectMapper();
|
conditions = mapper.readValue(MapUtil.getString(params, "conditions"), new TypeReference<Map<String, Object>>() {
|
});
|
}
|
|
return conditions;
|
}
|
|
// UserVos 에서 사용자 정보를 추출해서 문자열로 리턴해준다. - 주로 엑셀 download 에서 사용된다.
|
public static String convertUserVosToString(List<UserVo> userVos) {
|
StringBuilder stringBuilder = new StringBuilder();
|
int count = 0;
|
|
for (UserVo userVo : userVos) {
|
if (count > 0) {
|
stringBuilder.append("\n");
|
}
|
|
stringBuilder.append(userVo.getName());
|
stringBuilder.append("(");
|
stringBuilder.append(userVo.getAccount());
|
stringBuilder.append(")");
|
count++;
|
}
|
|
return stringBuilder.toString();
|
}
|
|
// DepartmentVos 에서 부서 정보를 추출해서 문자열로 리턴해준다. - 주로 엑셀 download 에서 사용된다.
|
public static String convertDepartmentVosToString(List<DepartmentVo> departmentVos) {
|
StringBuilder stringBuilder = new StringBuilder();
|
int count = 0;
|
|
for (DepartmentVo departmentVo : departmentVos) {
|
if (count > 0) {
|
stringBuilder.append("\n");
|
}
|
|
stringBuilder.append(departmentVo.getDepartmentName());
|
count++;
|
}
|
return stringBuilder.toString();
|
}
|
|
public static List<Date> findSearchPeriod(Date startDate, Date endDate) {
|
Calendar cal = Calendar.getInstance();
|
cal.setTime(endDate);
|
List<Date> days = Lists.newArrayList();
|
|
// 이번달 날짜 리스트 가져오기
|
while (cal.getTime().after(startDate)){
|
days.add(cal.getTime());
|
cal.add(Calendar.DATE, -1);
|
}
|
|
return days;
|
}
|
|
// 검색 일자를 구한다.
|
public static List<Date> findSearchPeriod(String searchPeriod) {
|
List<Date> searchDates = Lists.newArrayList();
|
|
switch (searchPeriod) {
|
case DateUtil.THIS_WEEK:
|
searchDates = DateUtil.getSearchDays(DateUtil.THIS_WEEK);
|
break;
|
case DateUtil.LAST_WEEK:
|
searchDates = DateUtil.getSearchDays(DateUtil.LAST_WEEK);
|
break;
|
case DateUtil.LAST_SEVEN_DAYS:
|
searchDates = DateUtil.getSearchDays(DateUtil.LAST_SEVEN_DAYS);
|
break;
|
case DateUtil.THIS_MONTH:
|
searchDates = DateUtil.getSearchDays(DateUtil.THIS_MONTH);
|
break;
|
case DateUtil.LAST_MONTH:
|
searchDates = DateUtil.getSearchDays(DateUtil.LAST_MONTH);
|
break;
|
case DateUtil.LAST_THIRTY_DAYS:
|
searchDates = DateUtil.getSearchDays(DateUtil.LAST_THIRTY_DAYS);
|
break;
|
}
|
|
return searchDates;
|
}
|
|
// 클라이언트의 브라우저 정보를 찾는다.
|
public static String getBrowser(HttpServletRequest request) {
|
String header = request.getHeader("User-Agent");
|
if (header.contains("MSIE") || header.contains("Trident")) {
|
return "MSIE";
|
}
|
else if (header.indexOf("Chrome") > -1) {
|
return "Chrome";
|
}
|
else if (header.indexOf("Opera") > -1) {
|
return "Opera";
|
}
|
return "Firefox";
|
}
|
|
// 브라우저 별로 파일 공백을 처리한다.
|
public static String getDisposition(String filename, String browser) throws Exception {
|
String encodedFilename = null;
|
|
switch (browser) {
|
case "MSIE":
|
case "Trident":
|
encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
|
break;
|
case "Firefox":
|
encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
|
break;
|
case "Opera":
|
encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
|
break;
|
case "Chrome":
|
StringBuilder sb = new StringBuilder();
|
for (int i = 0; i < filename.length(); i++) {
|
char c = filename.charAt(i);
|
if (c > '~') {
|
sb.append(URLEncoder.encode("" + c, "UTF-8"));
|
}
|
else {
|
sb.append(c);
|
}
|
}
|
encodedFilename = sb.toString();
|
break;
|
}
|
|
return encodedFilename;
|
}
|
|
// XSS 공격을 막기 위해 스크립트 태그를 없앤다. - 이슈 생성, 수정, 상세에서 태그를 살려야 하기 때문에 스크립트만 막는다.
|
public static String preventXss(String dirty) {
|
dirty = dirty.replaceAll("<script", "");
|
dirty = dirty.replaceAll("</script", "");
|
|
return dirty;
|
}
|
|
// InputStream 을 String 으로 변환
|
public static String getStringToInputStream(int responseCode, InputStream inputStream) {
|
StringBuffer response = new StringBuffer();
|
BufferedReader br = null;
|
|
try {
|
// 정상 호출
|
if (responseCode == HttpsURLConnection.HTTP_OK) {
|
br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
String inputLine;
|
while ((inputLine = br.readLine()) != null) {
|
response.append(inputLine);
|
}
|
}
|
} catch (IOException e) {
|
LOGGER.debug("CommonUtil.getStringToInputStream Error " + e.getMessage());
|
} finally {
|
if (br != null) {
|
try {
|
br.close();
|
} catch (IOException e) {
|
LOGGER.debug("CommonUtil.getStringToInputStream Error " + e.getMessage());
|
}
|
}
|
}
|
|
return response.toString();
|
}
|
|
// 숫자 인지 여부 확인
|
public static boolean isNumeric(String str) {
|
try {
|
Double.parseDouble(str);
|
return true;
|
} catch (NumberFormatException e) {
|
return false;
|
}
|
}
|
|
// 두 배열에서 겹치지 않는 항목을 찾아낸다.
|
public static List<Long> searchChangeList(List<Long> targetIds, List<Long> searchIds) {
|
List<Long> results = Lists.newArrayList();
|
|
for (Long searchId : searchIds) {
|
boolean exist = false;
|
|
for (Long targetId : targetIds) {
|
if (searchId.equals(targetId)) {
|
exist = true;
|
break;
|
}
|
}
|
|
if (!exist) {
|
results.add(searchId);
|
}
|
}
|
|
return results;
|
}
|
|
// 메일을 받는 사용자가 사용하고 있는 언어 정보를 가져온다.
|
public static Locale getUserLanguage(String language) {
|
Locale locale;
|
|
switch (language) {
|
case "ko":
|
locale = new Locale("ko", "KR");
|
break;
|
case "en":
|
locale = new Locale("en", "US");
|
break;
|
case "ja":
|
locale = new Locale("ja", "JP");
|
break;
|
case "vi":
|
locale = new Locale("vi", "VN");
|
break;
|
default:
|
locale = new Locale("ko", "KR");
|
}
|
|
return locale;
|
}
|
|
// 숫자에 3자리 마다 , 를 찍어준다
|
public static String getDecimalFormat(Object object) {
|
DecimalFormat decimalFormat = new DecimalFormat("###,###");
|
return decimalFormat.format(object);
|
}
|
|
// 엑셀 import 데이터에서 cell 값을 문자열로 변환한다.
|
public static String convertExcelStringToCell(Cell cell) {
|
String cellValue = "";
|
|
switch (cell.getCellType()) {
|
case Cell.CELL_TYPE_NUMERIC :
|
|
// 날짜 형식인 경우 날짜로 변환
|
if (HSSFDateUtil.isCellDateFormatted(cell)) {
|
Date date = cell.getDateCellValue();
|
cellValue = DateUtil.convertDateToStr(date, "yyyy-MM-dd HH:mm:ss");
|
|
} else {
|
double doubleValue = cell.getNumericCellValue();
|
int intValue;
|
|
if (doubleValue % 1 == 0) {
|
intValue = (int)doubleValue;
|
cellValue = intValue + "";
|
}
|
else {
|
cellValue = doubleValue + "";
|
}
|
}
|
break;
|
|
case Cell.CELL_TYPE_STRING :
|
cellValue = cell.getStringCellValue();
|
break;
|
|
case Cell.CELL_TYPE_FORMULA :
|
cellValue = cell.getCellFormula() + "";
|
break;
|
|
case Cell.CELL_TYPE_BOOLEAN :
|
cellValue = cell.getBooleanCellValue() + "";
|
break;
|
}
|
|
return cellValue;
|
}
|
|
// 웹 소켓 메세지 발송
|
public static void sendWebSocketMessage(SimpMessagingTemplate simpMessagingTemplate, Map<String, Object> messageMap) {
|
String url = MapUtil.getString(messageMap, "url");
|
String content = MapUtil.getString(messageMap, "message");
|
String account = MapUtil.getString(messageMap, "account");
|
|
if (StringUtils.isEmpty(url) || StringUtils.isEmpty(content)) {
|
LOGGER.error("Fail WebSocket Message - url or content empty");
|
return;
|
}
|
|
if (!StringUtils.isEmpty(account)) {
|
simpMessagingTemplate.convertAndSendToUser(account, url, content);
|
}
|
else {
|
simpMessagingTemplate.convertAndSend(url, content);
|
}
|
}
|
|
// 메인 url만 추출
|
public static String extractUrl(String content){
|
try {
|
String REGEX = "(http(s)?:\\/\\/)([a-z0-9\\w]+\\.*)+[a-z0-9]{2,4}";
|
Pattern p = Pattern.compile(REGEX, Pattern.CASE_INSENSITIVE);
|
Matcher m = p.matcher(content);
|
if (m.find()) {
|
return m.group();
|
}
|
return "";
|
} catch (Exception e) {
|
return "";
|
}
|
}
|
|
// 메인 url 추출을 위해 http: 확인
|
public static String getUrl(String fullUrl) {
|
if (fullUrl != null) {
|
if (fullUrl.indexOf("http") == -1) {
|
fullUrl = "http://" + fullUrl;
|
}
|
|
return extractUrl(fullUrl);
|
}
|
return "";
|
}
|
|
|
/**
|
* 정규식 검사(URL)
|
* @param url 대상 문자열(URL)
|
* @return 검사 결과
|
*/
|
public static boolean verifyUrl(String url) {
|
return verifyRegular(url, Regular.URL);
|
}
|
|
/**
|
* 정규식 검사(IP)
|
* @param ip 대상 문자열(IP)
|
* @return 검사 결과
|
*/
|
public static boolean verifyIp(String ip) {
|
return verifyRegular(ip, Regular.IP);
|
}
|
|
/**
|
* 정규식 검사
|
* @param value 대상 문자열
|
* @param regular 정규식 검사를 할 정규식 구문
|
* @return 검사 결과
|
*/
|
public static boolean verifyRegular(String value, String regular) {
|
if (!StringUtils.isEmpty(value)) {
|
return Pattern.matches(regular, value);
|
}
|
return false;
|
}
|
}
|