diff --git a/src/main/java/io/company/localhost/common/security/service/CustomRememberMeServices.java b/src/main/java/io/company/localhost/common/security/service/CustomRememberMeServices.java index 29b1386..1d0a57f 100644 --- a/src/main/java/io/company/localhost/common/security/service/CustomRememberMeServices.java +++ b/src/main/java/io/company/localhost/common/security/service/CustomRememberMeServices.java @@ -153,8 +153,6 @@ public class CustomRememberMeServices implements RememberMeServices { return expectedSignature.equals(signature); } - // 현재는 id만 담는디 - // 만약 바꾼다면 findById로 정보체크 하는데 idx + id 로 체크 하는 거 만들어야 할 듯 private String generateSignature(String username, long expiryTime) { try { String data = username + DELIMITER + expiryTime; diff --git a/src/main/java/io/company/localhost/common/wrapper/CachedBodyRequestWrapper.java b/src/main/java/io/company/localhost/common/wrapper/CachedBodyRequestWrapper.java index fadce3a..e3af23f 100644 --- a/src/main/java/io/company/localhost/common/wrapper/CachedBodyRequestWrapper.java +++ b/src/main/java/io/company/localhost/common/wrapper/CachedBodyRequestWrapper.java @@ -16,7 +16,6 @@ package io.company.localhost.common.wrapper; import com.fasterxml.jackson.core.type.TypeReference; import io.company.localhost.utils.JacksonUtil; -import io.netty.handler.codec.ValueConverter; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; @@ -24,6 +23,8 @@ import jakarta.servlet.http.HttpServletRequestWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; import java.io.*; import java.nio.charset.Charset; @@ -41,11 +42,11 @@ public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { private final byte[] cachedBody; - private ValueConverter targetConvert; - public CachedBodyRequestWrapper(HttpServletRequest request) throws IOException { super(request); + String contentType = request.getContentType(); + String characterEncoding = request.getCharacterEncoding(); if (!StringUtils.hasText(characterEncoding)) { characterEncoding = StandardCharsets.UTF_8.name(); @@ -56,39 +57,54 @@ public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { // this.cachedBody = StreamUtils.copyToByteArray(requestInputStream); this.encoding = Charset.forName(characterEncoding); - // XSS 방지 - String requestBody = null; - try { - requestBody = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset()); - } catch (IOException e) { - log.error("StreamUtil.toString Exception", e); + // multipart/form 요청인지 확인 + if (contentType != null && contentType.toLowerCase().startsWith("multipart/")) { + this.cachedBody = handleMultipartRequest(request); + } else { + this.cachedBody = handleStandardRequestBody(request); } + } + private byte[] handleMultipartRequest(HttpServletRequest request) throws IOException { + // 멀티파트 요청 처리 + if (request instanceof MultipartHttpServletRequest) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + multipartRequest.getFileMap().forEach((name, file) -> { + try { + String fileName = file.getOriginalFilename(); + byte[] fileBytes = file.getBytes(); + // 파일 내용을 필요에 맞게 처리 (저장, 분석 등) + } catch (IOException e) { + throw new RuntimeException("파일 내용을 읽을 수 없습니다.", e); + } + }); + // 필요시 form 필드 처리도 추가 가능 + } else { + request = new StandardMultipartHttpServletRequest(request); + } + // 파일 처리 후 필요시 수정 + return new byte[0]; + } - if (requestBody == null) { - InputStream requestInputStream = request.getInputStream(); - this.cachedBody = StreamUtils.copyToByteArray(requestInputStream); - return; + private byte[] handleStandardRequestBody(HttpServletRequest request) throws IOException { + String requestBody; + try { + requestBody = StreamUtils.copyToString(request.getInputStream(), encoding); + } catch (IOException e) { + throw new IOException("요청 본문을 읽을 수 없습니다.", e); } Object bodyObject; - if (requestBody.startsWith("[")) { // List - bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>>() { - }); - } else { // Map - bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>() { - }); + if (requestBody.startsWith("[")) { + bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>>() {}); + } else { + bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>() {}); } - String newRequestBody = JacksonUtil.toJson(bodyObject); - if (Objects.isNull(newRequestBody)) { - newRequestBody = new String(""); - } - this.cachedBody = newRequestBody.getBytes(StandardCharsets.UTF_8); + return Objects.requireNonNullElse(newRequestBody, "").getBytes(StandardCharsets.UTF_8); } - /** json body 관련 메소드 START */ @Override public ServletInputStream getInputStream() throws IOException { return new CachedBodyServletInputStream(this.cachedBody); @@ -100,8 +116,6 @@ public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { return new BufferedReader(new InputStreamReader(byteArrayInputStream, encoding)); } - /** json body 관련 메소드 END */ - private static class CachedBodyServletInputStream extends ServletInputStream { private final InputStream cachedBodyInputStream; @@ -115,8 +129,7 @@ public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { try { return this.cachedBodyInputStream.available() == 0; } catch (IOException e) { - log.error("", e); - return false; + return true; } } @@ -136,5 +149,6 @@ public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { } } - } + + diff --git a/src/main/java/io/company/localhost/controller/common/TestController.java b/src/main/java/io/company/localhost/controller/common/TestController.java index 384cdd5..88e60b8 100644 --- a/src/main/java/io/company/localhost/controller/common/TestController.java +++ b/src/main/java/io/company/localhost/controller/common/TestController.java @@ -23,6 +23,7 @@ import io.company.localhost.service.TestService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; @Slf4j @RequestMapping("/api/test/") @@ -75,4 +76,10 @@ public class TestController { return ApiResponse.ok("OK"); } + @ParameterCheck + @PostMapping("fileTest") + public ApiResponse fileTest(@RequestParam("file") MultipartFile file, + @ReqMap MapDto map) { + return ApiResponse.ok("OK"); + } }