보안점검 소스 수정(portal-service)

This commit is contained in:
shinmj
2021-11-18 15:57:47 +09:00
parent bc24c9f706
commit 8c34b5da6e
7 changed files with 131 additions and 100 deletions

View File

@@ -72,6 +72,10 @@ public class AttachmentRepositoryImpl implements AttachmentRepositoryCustom{
.where(attachment.attachmentId.code.eq(attachmentCode))
.fetchOne();
if (seq == null) {
seq = 0L;
}
return AttachmentId.builder()
.code(attachmentCode)
.seq(seq+1L)

View File

@@ -11,6 +11,7 @@ import org.egovframe.cloud.portalservice.api.attachment.dto.*;
import org.egovframe.cloud.portalservice.domain.attachment.Attachment;
import org.egovframe.cloud.portalservice.domain.attachment.AttachmentId;
import org.egovframe.cloud.portalservice.domain.attachment.AttachmentRepository;
import org.egovframe.cloud.portalservice.utils.PortalUtils;
import org.egovframe.cloud.portalservice.utils.StorageUtils;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
@@ -235,7 +236,7 @@ public class AttachmentService extends AbstractService {
* @return 생성된 첨부파일 코드
*/
public String save(List<AttachmentTempSaveRequestDto> saveRequestDtoList) {
String attachmentCode = RandomStringUtils.randomAlphanumeric(20);
String attachmentCode = PortalUtils.randomAlphanumeric(20);
for (int i = 0; i < saveRequestDtoList.size(); i++) {
AttachmentTempSaveRequestDto requestDto = saveRequestDtoList.get(i);
AttachmentId attachmentId = AttachmentId.builder()
@@ -357,7 +358,7 @@ public class AttachmentService extends AbstractService {
*/
public String uploadAndSave(List<MultipartFile> files, AttachmentUploadRequestDto uploadRequestDto) {
String basePath = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
String attachmentCode = RandomStringUtils.randomAlphanumeric(20);
String attachmentCode = PortalUtils.randomAlphanumeric(20);
for (int i = 0; i < files.size(); i++) {
AttachmentId attachmentId = AttachmentId.builder()

View File

@@ -2,6 +2,7 @@ package org.egovframe.cloud.portalservice.utils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.egovframe.cloud.common.exception.BusinessException;
import org.egovframe.cloud.common.exception.BusinessMessageException;
import org.egovframe.cloud.common.exception.dto.ErrorCode;
@@ -78,16 +79,8 @@ public class FileStorageUtils implements StorageUtils {
*/
public Path getStorePath(String basePath) {
StringBuffer sb = new StringBuffer();
sb.append(fileStorageLocation.toString());
if (!basePath.equals("")) {
sb.append("/");
sb.append(StringUtils.cleanPath(basePath));
}
try {
Path path = Paths.get(StringUtils.cleanPath(sb.toString()))
.toAbsolutePath().normalize();
Path path = fileStorageLocation.resolve(basePath);
Files.createDirectories(path);
return path;
} catch (IOException ex) {
@@ -118,10 +111,11 @@ public class FileStorageUtils implements StorageUtils {
*/
public String renameTemp(String physicalFileName) {
String rename = physicalFileName.replace(".temp", "");
//물리적 파일 처리
Path path = getStorePath("");
File file = new File(path + "/" + physicalFileName);
File renameFile = new File(path + "/" + rename);
File file = path.resolve(physicalFileName).toFile();
File renameFile = path.resolve(rename).toFile();
try {
file.renameTo(renameFile);
} catch (NullPointerException ex) {
@@ -143,8 +137,7 @@ public class FileStorageUtils implements StorageUtils {
try {
Path path = getStorePath(basePath);
File file = new File(path + "/" + filename);
File file = path.resolve(filename).toFile();
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodeBytes = decoder.decode(requestDto.getFileBase64().getBytes());
@@ -257,9 +250,7 @@ public class FileStorageUtils implements StorageUtils {
public Resource downloadFile(String filename) {
Path path = getStorePath("");
try {
Path filePath = Paths.get(StringUtils.cleanPath(path.toString() + StringUtils.cleanPath("/" + filename)))
.toAbsolutePath().normalize();
Resource resource = new UrlResource(filePath.toUri());
Resource resource = new UrlResource(path.resolve(filename).toUri());
if (resource.exists()) {
return resource;
@@ -319,9 +310,8 @@ public class FileStorageUtils implements StorageUtils {
public boolean deleteFile(String filename) {
Path path = getStorePath("");
try {
Path filePath = Paths.get(StringUtils.cleanPath(path.toString() + StringUtils.cleanPath("/" + filename)))
.toAbsolutePath().normalize();
return Files.deleteIfExists(filePath);
System.out.println("==== paths :" + path.resolve(filename));
return Files.deleteIfExists(path.resolve(filename));
} catch (IOException e) {
log.error("Could not deleted file.", e);
return false;

View File

@@ -1,5 +1,6 @@
package org.egovframe.cloud.portalservice.utils;
import java.util.ArrayList;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.net.ftp.FTPClient;
@@ -58,7 +59,7 @@ public class FtpClientDto {
}
public FtpClientDto addFiles(List<File> files, String path) {
this.files = files;
this.files = new ArrayList<>(files);
this.path = path;
return this;
}

View File

@@ -1,7 +1,9 @@
package org.egovframe.cloud.portalservice.utils;
import java.nio.file.Files;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
@@ -366,15 +368,15 @@ public class FtpStorageUtils implements StorageUtils {
*/
public AttachmentImageResponseDto loadImage(String imagename) {
try {
Resource resource = new UrlResource(environment.getProperty("file.url") + StringUtils.cleanPath("/" + imagename));
InputStream inputStream = new URL(resource.getURL().toString()).openStream();
String paths = environment.getProperty("file.url") + imagename;
Resource resource = new UrlResource(paths);
InputStream inputStream = resource.getInputStream();
byte[] data = IOUtils.toByteArray(inputStream);
inputStream.close();
// get mime type
URLConnection connection = new URL(resource.getURL().toString()).openConnection();
String contentType = connection.getContentType();
String contentType = Files.probeContentType(resource.getFile().toPath());
return AttachmentImageResponseDto.builder()
.mimeType(contentType)
@@ -434,14 +436,14 @@ public class FtpStorageUtils implements StorageUtils {
FtpClientDto ftpClientDto = new FtpClientDto(environment);
this.connect(ftpClientDto);
FTPClient ftpClient = ftpClientDto.getFtpClient();
// 디렉토리 생성 및 권한 부여
String directory = StringUtils.cleanPath(ftpClientDto.getDirectory() + "/" + basePath);
makePermissionDirectory(ftpClient, directory);
Path directory = Paths.get(ftpClientDto.getDirectory()).toAbsolutePath().normalize();
directory.resolve(basePath);
makePermissionDirectory(ftpClient, directory.toString());
this.disconnect(ftpClient);
return Paths.get(directory).toAbsolutePath().normalize();
return directory;
} catch (IOException ex) {
log.error("Could not create file store directory.", ex);
// 파일을 저장할 수 없습니다. 다시 시도해 주세요.

View File

@@ -1,12 +1,11 @@
package org.egovframe.cloud.portalservice.utils;
import org.egovframe.cloud.common.config.GlobalConstant;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.UUID;
import org.apache.commons.io.FilenameUtils;
import org.springframework.util.StringUtils;
/**
@@ -28,42 +27,69 @@ import java.util.UUID;
*/
public class PortalUtils {
/**
* '-'을 제거한 uuid 생성
*
* @return
*/
public static String getUUID() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
/**
* '-'을 제거한 uuid 생성
*
* @return
*/
public static String getUUID() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
/**
* 물리적 파일 이름 생성
*
* @param originalFileName
* @param isTemp
* @return
*/
public static String getPhysicalFileName(String originalFileName, boolean isTemp) {
String ext = StringUtils.getFilenameExtension(originalFileName);
StringBuffer sb = new StringBuffer();
sb.append(getUUID());
sb.append(".");
sb.append(ext);
if (isTemp) {
sb.append(".temp");
}
return StringUtils.cleanPath(sb.toString());
}
/**
* 물리적 파일 이름 생성 (.temp)
*
* @param originalFileName
* @return
*/
public static String getPhysicalFileName(String originalFileName) {
return getPhysicalFileName(originalFileName, true);
}
/**
* 물리적 파일 이름 생성
* SecureRandom을 활용한 랜덤 생성
*
* @param originalFileName
* @param isTemp
* @param count
* @return
*/
public static String getPhysicalFileName(String originalFileName, boolean isTemp) {
String ext = StringUtils.getFilenameExtension(originalFileName);
StringBuffer sb = new StringBuffer();
sb.append(getUUID());
sb.append(".");
sb.append(ext);
if(isTemp){
sb.append(".temp");
public static String randomAlphanumeric(int count) {
char[] charSet = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@',
'#', '$', '%', '^', '&'};
StringBuffer sb = new StringBuffer();
SecureRandom sr = new SecureRandom();
sr.setSeed(LocalDateTime.now().getNano());
int idx = 0;
int len = charSet.length;
for (int i = 0; i < count; i++) {
idx = sr.nextInt(len);
sb.append(charSet[idx]);
}
return StringUtils.cleanPath(sb.toString());
}
/**
* 물리적 파일 이름 생성 (.temp)
*
* @param originalFileName
* @return
*/
public static String getPhysicalFileName(String originalFileName) {
return getPhysicalFileName(originalFileName, true);
}
return sb.toString();
}
}

View File

@@ -1,33 +1,8 @@
package org.egovframe.cloud.portalservice.api.attachment;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.egovframe.cloud.portalservice.api.attachment.dto.*;
import org.egovframe.cloud.portalservice.domain.attachment.Attachment;
import org.egovframe.cloud.portalservice.domain.attachment.AttachmentRepository;
import org.egovframe.cloud.portalservice.service.attachment.AttachmentService;
import org.egovframe.cloud.portalservice.util.RestResponsePage;
import org.egovframe.cloud.portalservice.utils.FileStorageUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -38,8 +13,43 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentBase64RequestDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentEditorResponseDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentFileResponseDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentResponseDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentTempSaveRequestDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentUpdateRequestDto;
import org.egovframe.cloud.portalservice.api.attachment.dto.AttachmentUploadRequestDto;
import org.egovframe.cloud.portalservice.domain.attachment.Attachment;
import org.egovframe.cloud.portalservice.domain.attachment.AttachmentRepository;
import org.egovframe.cloud.portalservice.service.attachment.AttachmentService;
import org.egovframe.cloud.portalservice.util.RestResponsePage;
import org.egovframe.cloud.portalservice.utils.FileStorageUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
@Slf4j
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@@ -47,9 +57,6 @@ import static org.assertj.core.api.Assertions.assertThat;
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
@ActiveProfiles(profiles = "test")
class AttachmentApiControllerTest {
@LocalServerPort
private int port;
@Autowired
TestRestTemplate restTemplate;
@@ -282,6 +289,7 @@ class AttachmentApiControllerTest {
List<AttachmentTempSaveRequestDto> saveRequestDtoList = getTempSaveDto(2);
String attachmentCode = attachmentService.save(saveRequestDtoList);
System.out.println("attachmentCode : " + attachmentCode);
String url = "/api/v1/attachments/"+attachmentCode;
//when
@@ -363,6 +371,7 @@ class AttachmentApiControllerTest {
}
@Test
@Order(1)
public void 관리자_첨부파일_목록_검색조회_정상() throws Exception {
//given
List<AttachmentTempSaveRequestDto> saveRequestDtoList1 = getTempSaveDto(2);
@@ -535,8 +544,6 @@ class AttachmentApiControllerTest {
);
}
saveRequestDtoList.stream().forEach(System.out::println);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();