tsxCopy code// app/posts/[id]/page.tsximport { useRouter } from'next/navigation';interfacePostProps {params: { id:string };}exportdefaultfunctionPostPage({ params }:PostProps) {const { id } = params;// Fetch post data based on 'id'return (<div><h1>Post #{id}</h1><p>This is the content of post {id}.</p></div>);}
설명:
동적 세그먼트:[id]는 경로에서 동적 세그먼트를 나타내며, URL에서 id 매개변수를 캡처합니다.
매개변수 접근:params 객체는 동적 매개변수를 포함하며, 컴포넌트 내에서 접근할 수 있습니다.
경로 일치:/posts/*와 일치하는 모든 경로, 예를 들어 /posts/1, /posts/abc 등이 이 컴포넌트에 의해 처리됩니다.
tsxCopy code// app/dashboard/settings/profile/page.tsxexportdefaultfunctionProfileSettingsPage() {return (<div><h1>Profile Settings</h1><p>Manage your profile information here.</p></div>);}
설명:
깊은 중첩:dashboard/settings/profile/ 내부의 page.tsx 파일은 /dashboard/settings/profile 경로에 해당합니다.
계층 반영: 디렉토리 구조는 URL 경로를 반영하여 유지 관리성과 명확성을 향상시킵니다.
모든 경로 처리
모든 경로 처리는 여러 중첩 세그먼트 또는 알 수 없는 경로를 처리하여 경로 처리의 유연성을 제공합니다.
// app/[...slug]/page.tsxinterfaceCatchAllProps {params: { slug:string[] };}exportdefaultfunctionCatchAllPage({ params }:CatchAllProps) {const { slug } = params;constfullPath=`/${slug.join('/')}`;return (<div><h1>Catch-All Route</h1><p>You have navigated to: {fullPath}</p></div>);}
설명:
Catch-All 세그먼트:[...slug]는 남은 모든 경로 세그먼트를 배열로 캡처합니다.
사용법: 사용자 생성 경로, 중첩 카테고리 등과 같은 동적 라우팅 시나리오를 처리하는 데 유용합니다.
경로 일치:/anything/here, /foo/bar/baz와 같은 경로는 이 구성 요소에 의해 처리됩니다.
잠재적인 클라이언트 측 취약점
Next.js는 안전한 기반을 제공하지만, 부적절한 코딩 관행은 취약점을 도입할 수 있습니다. 주요 클라이언트 측 취약점은 다음과 같습니다:
교차 사이트 스크립팅 (XSS)
XSS 공격은 신뢰할 수 있는 웹사이트에 악성 스크립트가 주입될 때 발생합니다. 공격자는 사용자의 브라우저에서 스크립트를 실행하여 데이터를 훔치거나 사용자를 대신하여 작업을 수행할 수 있습니다.
취약한 코드의 예:
// Dangerous: Injecting user input directly into HTMLfunctionComment({ userInput }) {return <divdangerouslySetInnerHTML={{ __html: userInput }} />;}
왜 취약한가: 신뢰할 수 없는 입력과 함께 dangerouslySetInnerHTML을 사용하면 공격자가 악성 스크립트를 주입할 수 있습니다.
클라이언트 측 템플릿 주입
사용자 입력이 템플릿에서 부적절하게 처리될 때 발생하며, 공격자가 템플릿이나 표현식을 주입하고 실행할 수 있게 합니다.
취약한 코드의 예:
import React from'react';import ejs from'ejs';functionRenderTemplate({ template, data }) {consthtml=ejs.render(template, data);return <divdangerouslySetInnerHTML={{ __html: html }} />;}
왜 취약한가:template 또는 data에 악의적인 내용이 포함되면 의도하지 않은 코드 실행으로 이어질 수 있습니다.
클라이언트 경로 탐색
이는 공격자가 클라이언트 측 경로를 조작하여 Cross-Site Request Forgery (CSRF)와 같은 의도하지 않은 작업을 수행할 수 있게 하는 취약점입니다. 서버 측 경로 탐색이 서버의 파일 시스템을 목표로 하는 것과 달리, CSPT는 클라이언트 측 메커니즘을 악용하여 합법적인 API 요청을 악의적인 엔드포인트로 리다이렉트하는 데 중점을 둡니다.
취약한 코드의 예:
Next.js 애플리케이션은 사용자가 파일을 업로드하고 다운로드할 수 있도록 합니다. 다운로드 기능은 클라이언트 측에서 구현되어 있으며, 사용자가 다운로드할 파일 경로를 지정할 수 있습니다.
javascriptCopy code// pages/api/users/[id].jsexportdefaultfunctionhandler(req, res) {const {query: { id },method,} = req;switch (method) {case'GET':// Fetch user data based on 'id'res.status(200).json({ userId: id, name:'John Doe' });break;case'PUT':// Update user data based on 'id'res.status(200).json({ message:`User ${id} updated.` });break;case'DELETE':// Delete user based on 'id'res.status(200).json({ message:`User ${id} deleted.` });break;default:res.setHeader('Allow', ['GET','PUT','DELETE']);res.status(405).end(`Method ${method} Not Allowed`);}}
설명:
동적 세그먼트: 대괄호([id].js)는 동적 경로 세그먼트를 나타냅니다.
매개변수 접근:req.query.id를 사용하여 동적 매개변수에 접근합니다.
메서드 처리: 조건 논리를 활용하여 다양한 HTTP 메서드(GET, PUT, DELETE 등)를 처리합니다.
다양한 HTTP 메서드 처리
기본 API 경로 예제는 단일 함수 내에서 모든 HTTP 메서드를 처리하지만, 코드의 명확성과 유지 관리를 위해 각 메서드를 명시적으로 처리하도록 구조화할 수 있습니다.
예제:
javascriptCopy code// pages/api/posts.jsexportdefaultasyncfunctionhandler(req, res) {const { method } = req;switch (method) {case'GET':// Handle GET requestres.status(200).json({ message:'Fetching posts.' });break;case'POST':// Handle POST requestres.status(201).json({ message:'Post created.' });break;default:res.setHeader('Allow', ['GET','POST']);res.status(405).end(`Method ${method} Not Allowed`);}}
모범 사례:
관심사의 분리: 서로 다른 HTTP 메서드에 대한 로직을 명확하게 분리합니다.
응답 일관성: 클라이언트 측 처리를 용이하게 하기 위해 일관된 응답 구조를 보장합니다.
오류 처리: 지원되지 않는 메서드와 예상치 못한 오류를 우아하게 처리합니다.
CORS 구성
어떤 출처가 API 경로에 접근할 수 있는지 제어하여 교차 출처 리소스 공유(CORS) 취약점을 완화합니다.
잘못된 구성 예:
// app/api/data/route.jsexportasyncfunctionGET(request) {returnnewResponse(JSON.stringify({ data:'Public Data' }), {status:200,headers: {'Access-Control-Allow-Origin':'*',// Allows any origin'Access-Control-Allow-Methods':'GET, POST, PUT, DELETE',},});}
CORS는 또한 middleware.ts 파일 내의 모든 API 경로에서 구성할 수 있습니다:
// app/middleware.tsimport { NextResponse } from'next/server';importtype { NextRequest } from'next/server';exportfunctionmiddleware(request:NextRequest) {constallowedOrigins= ['https://yourdomain.com','https://sub.yourdomain.com'];constorigin=request.headers.get('Origin');constresponse=NextResponse.next();if (allowedOrigins.includes(origin ||'')) {response.headers.set('Access-Control-Allow-Origin', origin ||'');response.headers.set('Access-Control-Allow-Methods','GET, POST, PUT, DELETE, OPTIONS');response.headers.set('Access-Control-Allow-Headers','Content-Type, Authorization');// If credentials are needed:// response.headers.set('Access-Control-Allow-Credentials', 'true');}// Handle preflight requestsif (request.method ==='OPTIONS') {returnnewResponse(null, {status:204,headers:response.headers,});}return response;}exportconstconfig= {matcher:'/api/:path*',// Apply to all API routes};
문제:
Access-Control-Allow-Origin: '*': 모든 웹사이트가 API에 접근할 수 있도록 허용하여, 악의적인 사이트가 제한 없이 API와 상호작용할 수 있게 할 수 있습니다.
광범위한 메서드 허용: 모든 메서드를 허용하면 공격자가 원하지 않는 작업을 수행할 수 있습니다.
공격자가 이를 악용하는 방법:
공격자는 악의적인 웹사이트를 만들어 API에 요청을 보내고, 인증된 사용자를 대신하여 데이터 검색, 데이터 조작 또는 원하지 않는 작업을 트리거하는 기능을 악용할 수 있습니다.
Next.js는 성능을 위해 이미지를 최적화하지만, 잘못된 구성은 신뢰할 수 없는 소스가 악성 콘텐츠를 주입할 수 있는 보안 취약점을 초래할 수 있습니다.
잘못된 구성 예:
// next.config.jsmodule.exports= {images: {domains: ['*'],// Allows images from any domain},};
문제:
'*': 신뢰할 수 없거나 악의적인 도메인을 포함하여 모든 외부 소스에서 이미지를 로드할 수 있도록 허용합니다. 공격자는 악성 페이로드나 사용자를 오도하는 콘텐츠가 포함된 이미지를 호스팅할 수 있습니다.
또 다른 문제는 누구나 이미지를 업로드할 수 있는 도메인을 허용하는 것입니다 (예: raw.githubusercontent.com)
공격자가 이를 악용하는 방법:
악성 소스에서 이미지를 주입함으로써 공격자는 피싱 공격을 수행하거나, 오해의 소지가 있는 정보를 표시하거나, 이미지 렌더링 라이브러리의 취약점을 악용할 수 있습니다.
환경 변수 노출
API 키 및 데이터베이스 자격 증명과 같은 민감한 정보를 클라이언트에 노출하지 않고 안전하게 관리합니다.
a. 민감한 변수 노출
잘못된 구성 예:
// next.config.jsmodule.exports= {env: {SECRET_API_KEY:process.env.SECRET_API_KEY,// Exposed to the clientNEXT_PUBLIC_API_URL:process.env.NEXT_PUBLIC_API_URL,// Correctly prefixed for client},};
문제:
SECRET_API_KEY:NEXT_PUBLIC_ 접두사가 없으면 Next.js는 변수를 클라이언트에 노출하지 않습니다. 그러나 실수로 접두사가 붙으면(예: NEXT_PUBLIC_SECRET_API_KEY), 클라이언트 측에서 접근할 수 있게 됩니다.
공격자가 이를 악용하는 방법:
민감한 변수가 클라이언트에 노출되면, 공격자는 클라이언트 측 코드나 네트워크 요청을 검사하여 이를 검색하고, API, 데이터베이스 또는 기타 서비스에 대한 무단 접근을 얻을 수 있습니다.
리디렉션
응용 프로그램 내에서 URL 리디렉션 및 재작성 관리를 통해 사용자가 적절하게 안내되도록 하여 열린 리디렉션 취약점이 발생하지 않도록 합니다.
a. 열린 리디렉션 취약점
잘못된 구성 예:
// next.config.jsmodule.exports= {asyncredirects() {return [{source:'/redirect',destination: (req) =>req.query.url,// Dynamically redirects based on query parameterpermanent:false,},];},};
문제:
동적 목적지: 사용자가 임의의 URL을 지정할 수 있어 오픈 리디렉션 공격을 가능하게 합니다.
사용자 입력 신뢰: 사용자에 의해 제공된 URL로 리디렉션하는 것은 검증 없이 이루어질 경우 피싱, 악성 소프트웨어 배포 또는 자격 증명 도용으로 이어질 수 있습니다.
공격자가 이를 악용하는 방법:
공격자는 귀하의 도메인에서 시작된 것처럼 보이는 URL을 만들어 사용자를 악성 사이트로 리디렉션할 수 있습니다. 예를 들어:
.env 파일 사용: API 키와 같은 변수를 .env.local에 저장 (버전 관리에서 제외).
변수를 안전하게 접근:process.env.VARIABLE_NAME을 사용하여 환경 변수에 접근.
클라이언트에 비밀 노출 금지: 민감한 변수는 서버 측에서만 사용되도록 보장.
예시:
// next.config.jsmodule.exports= {env: {API_KEY:process.env.API_KEY,// Accessible on both client and serverSECRET_KEY:process.env.SECRET_KEY,// Be cautious if accessible on the client},};
참고: 변수를 서버 측 전용으로 제한하려면 env 객체에서 생략하거나 클라이언트 노출을 위해 NEXT_PUBLIC_로 접두사를 붙이십시오.
인증 및 권한 부여
접근 방식:
세션 기반 인증: 쿠키를 사용하여 사용자 세션을 관리합니다.
토큰 기반 인증: 상태 비저장 인증을 위해 JWT를 구현합니다.
타사 제공업체:next-auth와 같은 라이브러리를 사용하여 OAuth 제공업체(예: Google, GitHub)와 통합합니다.