diff options
| author | joonhoekim <26rote@gmail.com> | 2025-09-09 05:55:01 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-09-09 05:55:01 +0000 |
| commit | ce2d3097d034a1c5dd29c6cf3740556d41c7e880 (patch) | |
| tree | 32eb9480bf141e03ce6c7010ccabf1bda1fd278e /app/api | |
| parent | e06913008f124ce8e7389fbdc1e57206ce9bbb2b (diff) | |
(김준회) 협력업체관리 파일다운로드 라우트 오류 수정
- public/api/files/... 형태로 찾는 문제를 /api/files/... 형태의 경로를 찾도록 변경
Diffstat (limited to 'app/api')
| -rw-r--r-- | app/api/vendors/attachments/download-all/route.ts | 35 | ||||
| -rw-r--r-- | app/api/vendors/attachments/download/route.ts | 34 |
2 files changed, 59 insertions, 10 deletions
diff --git a/app/api/vendors/attachments/download-all/route.ts b/app/api/vendors/attachments/download-all/route.ts index 4520cb2d..a1e56bba 100644 --- a/app/api/vendors/attachments/download-all/route.ts +++ b/app/api/vendors/attachments/download-all/route.ts @@ -44,8 +44,11 @@ export async function GET(request: NextRequest) { ); } - // 업로드 기본 경로 - const basePath = process.env.UPLOAD_DIR || path.join(process.cwd(), 'public'); + // 환경에 따른 기본 경로 설정 (/api/files/ 와 동일한 로직) + const nasPath = process.env.NAS_PATH || "/evcp_nas"; + const basePath = process.env.NODE_ENV === 'production' + ? nasPath + : path.join(process.cwd(), 'public'); // ZIP 생성 const zip = new JSZip(); @@ -60,16 +63,34 @@ export async function GET(request: NextRequest) { return; } - // filePath는 이미 /로 시작하므로 public 폴더에서의 상대 경로로 처리 - const normalizedPath = attachment.filePath.startsWith('/') - ? attachment.filePath.slice(1) // 앞의 '/' 제거 - : attachment.filePath; + // DB에 저장된 경로가 /api/files/vendors/[id]/[filename] 형태인 경우 처리 + let normalizedPath: string; + + if (attachment.filePath.startsWith('/api/files/')) { + // /api/files/vendors/[id]/[filename] -> vendors/[id]/[filename] + normalizedPath = attachment.filePath.replace('/api/files/', ''); + } else if (attachment.filePath.startsWith('/')) { + // 기존 방식: /vendors/[id]/[filename] -> vendors/[id]/[filename] + normalizedPath = attachment.filePath.slice(1); + } else { + // 상대 경로 그대로 사용 + normalizedPath = attachment.filePath; + } + + // 보안 검증: 경로 탐색 공격 방지 + if (normalizedPath.includes('..') || normalizedPath.includes('~')) { + console.warn(`위험한 경로 패턴: ${normalizedPath}`); + return; + } + const filePath = path.join(basePath, normalizedPath); + console.log(`파일 경로 확인: ${attachment.filePath} -> ${filePath}`); + // 파일 존재 확인 try { await fs.promises.access(filePath, fs.constants.F_OK); - } catch (e) { + } catch { console.warn(`파일이 존재하지 않습니다: ${filePath}`); return; // 파일이 없으면 건너뜀 } diff --git a/app/api/vendors/attachments/download/route.ts b/app/api/vendors/attachments/download/route.ts index 0151a699..1c9e5ddf 100644 --- a/app/api/vendors/attachments/download/route.ts +++ b/app/api/vendors/attachments/download/route.ts @@ -31,9 +31,37 @@ export async function GET(request: NextRequest) { ); } - // 파일 경로 구성 - const basePath = process.env.UPLOAD_DIR || path.join(process.cwd(), 'public'); - const filePath = path.join(basePath, attachment.filePath); + // 환경에 따른 기본 경로 설정 (/api/files/ 와 동일한 로직) + const nasPath = process.env.NAS_PATH || "/evcp_nas"; + const basePath = process.env.NODE_ENV === 'production' + ? nasPath + : path.join(process.cwd(), 'public'); + + // DB에 저장된 경로가 /api/files/vendors/[id]/[filename] 형태인 경우 처리 + let normalizedPath: string; + + if (attachment.filePath.startsWith('/api/files/')) { + // /api/files/vendors/[id]/[filename] -> vendors/[id]/[filename] + normalizedPath = attachment.filePath.replace('/api/files/', ''); + } else if (attachment.filePath.startsWith('/')) { + // 기존 방식: /vendors/[id]/[filename] -> vendors/[id]/[filename] + normalizedPath = attachment.filePath.slice(1); + } else { + // 상대 경로 그대로 사용 + normalizedPath = attachment.filePath; + } + + // 보안 검증: 경로 탐색 공격 방지 + if (normalizedPath.includes('..') || normalizedPath.includes('~')) { + return NextResponse.json( + { error: "안전하지 않은 파일 경로입니다." }, + { status: 400 } + ); + } + + const filePath = path.join(basePath, normalizedPath); + + console.log(`파일 경로 확인: ${attachment.filePath} -> ${filePath}`); // 파일 존재 확인 try { |
