Standardni Next.js projekat prati specifičnu strukturu fajlova i direktorijuma koja olakšava njegove funkcije kao što su rutiranje, API krajnje tačke i upravljanje statičkim resursima. Evo tipičnog rasporeda:
public/: Sadrži statičke resurse kao što su slike, fontovi i drugi fajlovi. Fajlovi ovde su dostupni na korenskom putu (/).
app/: Centralna direktorija za stranice, rasporede, komponente i API rute vaše aplikacije. Obuhvata App Router paradigmu, omogućavajući napredne funkcije usmeravanja i razdvajanje server-klijent komponenti.
app/layout.tsx: Definiše osnovni raspored za vašu aplikaciju, obavijajući sve stranice i pružajući dosledne UI elemente kao što su zaglavlja, podnožja i navigacione trake.
app/page.tsx: Služi kao ulazna tačka za osnovnu rutu /, renderujući početnu stranicu.
app/[route]/page.tsx: Rukuje statičnim i dinamičnim rutama. Svaka fascikla unutar app/ predstavlja segment rute, a page.tsx unutar tih fascikli odgovara komponenti rute.
app/api/: Sadrži API rute, omogućavajući vam da kreirate serverless funkcije koje obrađuju HTTP zahteve. Ove rute zamenjuju tradicionalnu pages/api direktoriju.
app/components/: Sadrži ponovo upotrebljive React komponente koje se mogu koristiti na različitim stranicama i rasporedima.
app/styles/: Sadrži globalne CSS fajlove i CSS Module za stilizovanje ograničeno na komponente.
app/utils/: Uključuje pomoćne funkcije, pomoćne module i drugu logiku koja nije UI, a koja se može deliti širom aplikacije.
.env.local: Čuva promenljive okruženja specifične za lokalno razvojno okruženje. Ove promenljive nisu uključene u kontrolu verzija.
next.config.js: Prilagođava ponašanje Next.js, uključujući webpack konfiguracije, promenljive okruženja i bezbednosne postavke.
tsconfig.json: Konfiguriše TypeScript postavke za projekat, omogućavajući proveru tipova i druge TypeScript funkcije.
package.json: Upravljanje zavisnostima projekta, skriptama i metapodacima.
README.md: Pruža dokumentaciju i informacije o projektu, uključujući uputstva za postavljanje, smernice za korišćenje i druge relevantne detalje.
yarn.lock / package-lock.json: Zaključava zavisnosti projekta na specifične verzije, osiguravajući dosledne instalacije širom različitih okruženja.
Klijentska Strana u Next.js
Ruting na Bazi Fajlova u app Direktoriji
Direktorija app je kamen temeljac rutiranja u najnovijim verzijama Next.js. Iskorišćava datotečni sistem za definisanje ruta, čineći upravljanje rutama intuitivnim i skalabilnim.
// app/about/page.tsxexportdefaultfunctionAboutPage() {return (<div><h1>About Us</h1><p>Learn more about our mission and values.</p></div>);}
Objašnjenje:
Definicija Rute: Datoteka page.tsx unutar about foldera odgovara ruti /about.
Renderovanje: Ova komponenta renderuje sadržaj za stranicu o nama.
Dinamičke Rute
Dinamičke rute omogućavaju rukovanje putanjama sa promenljivim segmentima, omogućavajući aplikacijama da prikazuju sadržaj na osnovu parametara kao što su ID-ovi, slug-ovi, itd.
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>);}
Objašnjenje:
Dinamički Segment:[id] označava dinamički segment u ruti, hvatajući id parametar iz URL-a.
Pristup Parametrima:params objekat sadrži dinamičke parametre, dostupne unutar komponente.
Usklađivanje Ruta: Svaka putanja koja se poklapa sa /posts/*, kao što su /posts/1, /posts/abc, itd., biće obrađena od strane ove komponente.
tsxCopy code// app/dashboard/settings/profile/page.tsxexportdefaultfunctionProfileSettingsPage() {return (<div><h1>Profile Settings</h1><p>Manage your profile information here.</p></div>);}
Objašnjenje:
Duboko Ugnježdenje: Datoteka page.tsx unutar dashboard/settings/profile/ odgovara ruti /dashboard/settings/profile.
Refleksija Hijerarhije: Struktura direktorijuma odražava URL putanju, poboljšavajući održivost i jasnoću.
Catch-All Rute
Catch-all rute obrađuju više ugnježdenih segmenata ili nepoznatih putanja, pružajući fleksibilnost u obradi ruta.
// 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>);}
Objašnjenje:
Catch-All Segment:[...slug] hvata sve preostale delove putanje kao niz.
Upotreba: Korisno za rukovanje dinamičkim scenarijima usmeravanja kao što su putanje koje generišu korisnici, ugnježdene kategorije, itd.
Usklađivanje Ruta: Putanje kao što su /anything/here, /foo/bar/baz, itd., se obrađuju od strane ove komponente.
Potencijalne Ranljivosti na Klijentskoj Strani
Dok Next.js pruža sigurnu osnovu, nepravilne prakse kodiranja mogu uvesti ranjivosti. Ključne ranjivosti na klijentskoj strani uključuju:
Cross-Site Scripting (XSS)
XSS napadi se dešavaju kada se zlonamerni skripti ubacuju u pouzdane veb sajtove. Napadači mogu izvršavati skripte u pregledačima korisnika, kradući podatke ili obavljajući radnje u ime korisnika.
Primer Ranljivog Koda:
// Dangerous: Injecting user input directly into HTMLfunctionComment({ userInput }) {return <divdangerouslySetInnerHTML={{ __html: userInput }} />;}
Zašto je ranjiv: Korišćenje dangerouslySetInnerHTML sa nepouzdanim ulazom omogućava napadačima da ubace zlonamerne skripte.
Injekcija Šablona na Klijentskoj Strani
Događa se kada se korisnički unosi nepravilno obrađuju u šablonima, omogućavajući napadačima da ubace i izvrše šablone ili izraze.
Primer Ranjivog Koda:
import React from'react';import ejs from'ejs';functionRenderTemplate({ template, data }) {consthtml=ejs.render(template, data);return <divdangerouslySetInnerHTML={{ __html: html }} />;}
Zašto je ranjiv: Ako template ili data sadrže zlonamerni sadržaj, to može dovesti do izvršenja nepredviđenog koda.
Klijentska putanja prolaska
To je ranjivost koja omogućava napadačima da manipulišu putanjama na klijentskoj strani kako bi izvršili nepredviđene radnje, kao što je Cross-Site Request Forgery (CSRF). Za razliku od prolaska putanje na serverskoj strani, koji cilja na datotečni sistem servera, CSPT se fokusira na iskorišćavanje mehanizama na klijentskoj strani kako bi preusmerio legitimne API zahteve na zlonamerne krajnje tačke.
Primer ranjivog koda:
A Next.js aplikacija omogućava korisnicima da otpremaju i preuzimaju datoteke. Funkcija preuzimanja je implementirana na klijentskoj strani, gde korisnici mogu da navedu putanju datoteke za preuzimanje.
Verovanje Klijentskim Unosima: Server-side API veruje i obrađuje filePath bez sanitizacije.
Potencijalne API Akcije: Ako API krajnja tačka izvršava akcije koje menjaju stanje (npr., brisanje, modifikacija datoteka), može se iskoristiti putem CSPT.
Server-Side u Next.js
Server-Side Rendering (SSR)
Stranice se renderuju na serveru pri svakom zahtevu, osiguravajući da korisnik dobije potpuno renderovani HTML. U ovom slučaju trebate kreirati svoj vlastiti prilagođeni server za obradu zahteva.
Upotrebe:
Dinamički sadržaj koji se često menja.
SEO optimizacija, jer pretraživači mogu indeksirati potpuno renderovanu stranicu.
Implementacija:
// pages/index.jsexportasyncfunctiongetServerSideProps(context) {constres=awaitfetch('https://api.example.com/data');constdata=awaitres.json();return { props: { data } };}functionHomePage({ data }) {return <div>{data.title}</div>;}exportdefault HomePage;
Static Site Generation (SSG)
Stranice se prethodno renderuju u vreme izgradnje, što rezultira bržim vremenima učitavanja i smanjenim opterećenjem servera.
Use Cases:
Sadržaj koji se ne menja često.
Blogovi, dokumentacija, marketinške stranice.
Implementation:
// pages/index.jsexportasyncfunctiongetStaticProps() {constres=awaitfetch('https://api.example.com/data');constdata=awaitres.json();return { props: { data }, revalidate:60 }; // Revalidate every 60 seconds}functionHomePage({ data }) {return <div>{data.title}</div>;}exportdefault HomePage;
Serverless Functions (API Routes)
Next.js omogućava kreiranje API krajnjih tačaka kao serverless funkcija. Ove funkcije se izvršavaju na zahtev bez potrebe za posvećenim serverom.
Use Cases:
Obrada slanja obrazaca.
Interakcija sa bazama podataka.
Obrada podataka ili integracija sa trećim stranama API-ima.
Implementation:
Sa uvođenjem app direktorijuma u Next.js 13, rutiranje i API obrada su postali fleksibilniji i moćniji. Ovaj moderni pristup se blisko usklađuje sa sistemom rutiranja zasnovanim na datotekama, ali uvodi poboljšane mogućnosti, uključujući podršku za server i klijentske komponente.
// app/api/hello/route.jsexportasyncfunctionPOST(request) {returnnewResponse(JSON.stringify({ message:'Hello from App Router!' }), {status:200,headers: { 'Content-Type':'application/json' },});}// Client-side fetch to access the API endpointfetch('/api/submit', {method:'POST',headers: { 'Content-Type':'application/json' },body:JSON.stringify({ name:'John Doe' }),}).then((res) =>res.json()).then((data) =>console.log(data));
Objašnjenje:
Lokacija: API rute se nalaze u app/api/ direktorijumu.
Naziv fajlova: Svaki API endpoint se nalazi u svojoj fascikli koja sadrži route.js ili route.ts fajl.
Izvezene funkcije: Umesto jednog podrazumevanog izvoza, specifične funkcije HTTP metoda (npr., GET, POST) se izvoze.
Obrada odgovora: Koristite Response konstruktor za vraćanje odgovora, omogućavajući veću kontrolu nad header-ima i status kodovima.
Kako obraditi druge putanje i metode:
Obrada specifičnih HTTP metoda
Next.js 13+ omogućava definisanje handler-a za specifične HTTP metode unutar istog route.js ili route.ts fajla, promovišući jasniji i organizovaniji kod.
Primer:
// app/api/users/[id]/route.jsexportasyncfunctionGET(request, { params }) {const { id } = params;// Fetch user data based on 'id'returnnewResponse(JSON.stringify({ userId: id, name:'Jane Doe' }), {status:200,headers: { 'Content-Type':'application/json' },});}exportasyncfunctionPUT(request, { params }) {const { id } = params;// Update user data based on 'id'returnnewResponse(JSON.stringify({ message:`User ${id} updated.` }), {status:200,headers: { 'Content-Type':'application/json' },});}exportasyncfunctionDELETE(request, { params }) {const { id } = params;// Delete user based on 'id'returnnewResponse(JSON.stringify({ message:`User ${id} deleted.` }), {status:200,headers: { 'Content-Type':'application/json' },});}
Objašnjenje:
Višestruki Izvozi: Svaka HTTP metoda (GET, PUT, DELETE) ima svoju funkciju za izvoz.
Parametri: Drugi argument omogućava pristup parametrima rute putem params.
Poboljšani Odgovori: Veća kontrola nad objektima odgovora, omogućavajući precizno upravljanje zaglavljem i status kodom.
Catch-All i Ugnježdene Rute
Next.js 13+ podržava napredne funkcije usmeravanja kao što su catch-all rute i ugnježdene API rute, omogućavajući dinamičnije i skalabilnije API strukture.
Sintaksa:[...] označava segment koji obuhvata sve, hvatajući sve ugnježdene putanje.
Upotreba: Korisno za API-je koji treba da obrade različite dubine ruta ili dinamičke segmente.
Primer ugnježdenih ruta:
// app/api/posts/[postId]/comments/[commentId]/route.jsexportasyncfunctionGET(request, { params }) {const { postId,commentId } = params;// Fetch specific comment for a postreturnnewResponse(JSON.stringify({ postId, commentId, comment:'Great post!' }), {status:200,headers: { 'Content-Type':'application/json' },});}
Objašnjenje:
Duboko Ugnježdenje: Omogućava hijerarhijske API strukture, odražavajući odnose resursa.
Pristup Parametrima: Lako pristupite više parametara rute putem params objekta.
Rukovanje API rutama u Next.js 12 i ranije
API Rute u pages Direktorijumu (Next.js 12 i ranije)
Pre nego što je Next.js 13 uveo app direktorijum i poboljšane mogućnosti rutiranja, API rute su se prvenstveno definisale unutar pages direktorijuma. Ovaj pristup se i dalje široko koristi i podržava u Next.js 12 i ranijim verzijama.
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`);}}
Pristup parametrima: Koristite req.query.id za pristup dinamičkom parametru.
Rukovanje metodama: Iskoristite uslovnu logiku za rukovanje različitim HTTP metodama (GET, PUT, DELETE, itd.).
Rukovanje različitim HTTP metodama
Dok osnovni primer API rute obrađuje sve HTTP metode unutar jedne funkcije, možete strukturirati svoj kod da obrađuje svaku metodu eksplicitno radi bolje jasnoće i održivosti.
Primer:
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`);}}
Najbolje Prakse:
Razdvajanje Zabrinutosti: Jasno razdvojiti logiku za različite HTTP metode.
Doslednost Odgovora: Osigurati dosledne strukture odgovora radi lakšeg rukovanja na klijentskoj strani.
Obrada Grešaka: Elegantno obraditi nepodržane metode i neočekivane greške.
CORS Konfiguracija
Kontrolisati koje izvore mogu pristupiti vašim API rutama, smanjujući ranjivosti vezane za deljenje resursa između različitih izvora (CORS).
Loš Primer Konfiguracije:
// 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',},});}
Napomena da se CORS takođe može konfigurisati u svim API rutama unutar middleware.ts datoteke:
// 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};
Problem:
Access-Control-Allow-Origin: '*': Dozvoljava bilo kojoj veb stranici da pristupi API-ju, potencijalno omogućavajući zlonamernim sajtovima da komuniciraju sa vašim API-jem bez ograničenja.
Široko dozvoljene metode: Dozvoljavanje svih metoda može omogućiti napadačima da izvrše neželjene radnje.
Kako napadači to koriste:
Napadači mogu kreirati zlonamerne veb stranice koje šalju zahteve vašem API-ju, potencijalno zloupotrebljavajući funkcionalnosti kao što su preuzimanje podataka, manipulacija podacima ili pokretanje neželjenih radnji u ime autentifikovanih korisnika.
Lako je koristiti kod koji koristi server takođe u kodu koji je izložen i koristi se na klijentskoj strani, najbolji način da se osigura da datoteka koda nikada nije izložena na klijentskoj strani je korišćenje ovog uvoza na početku datoteke:
import"server-only";
Ključne datoteke i njihove uloge
middleware.ts / middleware.js
Lokacija: Korenski deo projekta ili unutar src/.
Svrha: Izvršava kod u server-side serverless funkciji pre nego što se zahtev obradi, omogućavajući zadatke kao što su autentifikacija, preusmeravanja ili modifikovanje odgovora.
Tok izvršenja:
Dolazni zahtev: Middleware presreće zahtev.
Obrada: Izvršava operacije na osnovu zahteva (npr. provera autentifikacije).
Modifikacija odgovora: Može izmeniti odgovor ili preneti kontrolu sledećem handleru.
Svrha: Konfiguriše ponašanje Next.js, omogućavajući ili onemogućavajući funkcije, prilagođavajući webpack konfiguracije, postavljajući promenljive okruženja i konfigurišući nekoliko bezbednosnih funkcija.
Ključne bezbednosne konfiguracije:
Bezbednosni zaglavlja
Bezbednosna zaglavlja poboljšavaju bezbednost vaše aplikacije tako što upućuju pretraživače kako da rukuju sadržajem. Pomažu u ublažavanju raznih napada kao što su Cross-Site Scripting (XSS), Clickjacking i MIME type sniffing:
Next.js optimizuje slike za performanse, ali pogrešna podešavanja mogu dovesti do sigurnosnih ranjivosti, kao što je omogućavanje nepouzdanim izvorima da ubace zlonamerni sadržaj.
Primer lošeg podešavanja:
// next.config.jsmodule.exports= {images: {domains: ['*'],// Allows images from any domain},};
Problem:
'*': Dozvoljava učitavanje slika iz bilo kojeg spoljnog izvora, uključujući nepouzdane ili zlonamerne domene. Napadači mogu hostovati slike koje sadrže zlonamerne payload-e ili sadržaj koji obmanjuje korisnike.
Drugi problem može biti dozvoliti domenu gde bilo ko može da otpremi sliku (kao što je raw.githubusercontent.com)
Kako napadači to zloupotrebljavaju:
Ubacivanjem slika iz zlonamernih izvora, napadači mogu izvesti phishing napade, prikazati obmanjujuće informacije ili iskoristiti ranjivosti u bibliotekama za renderovanje slika.
Izloženost promenljivih okruženja
Upravljajte osetljivim informacijama kao što su API ključevi i kredencijali za bazu podataka na siguran način bez izlaganja klijentu.
a. Izlaganje osetljivih promenljivih
Loš primer konfiguracije:
// 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},};
Problem:
SECRET_API_KEY: Bez NEXT_PUBLIC_ prefiksa, Next.js ne izlaže varijable klijentu. Međutim, ako se greškom doda prefiks (npr., NEXT_PUBLIC_SECRET_API_KEY), postaje dostupno na strani klijenta.
Kako napadači to zloupotrebljavaju:
Ako su osetljive varijable izložene klijentu, napadači ih mogu preuzeti pregledanjem koda na strani klijenta ili mrežnih zahteva, stičući neovlašćen pristup API-ima, bazama podataka ili drugim uslugama.
Preusmeravanja
Upravljajte URL preusmeravanjima i prepisivanjima unutar vaše aplikacije, osiguravajući da su korisnici pravilno usmereni bez uvođenja ranjivosti otvorenog preusmeravanja.
a. Ranjivost otvorenog preusmeravanja
Primer loše konfiguracije:
// next.config.jsmodule.exports= {asyncredirects() {return [{source:'/redirect',destination: (req) =>req.query.url,// Dynamically redirects based on query parameterpermanent:false,},];},};
Problem:
Dinamička destinacija: Omogućava korisnicima da navedu bilo koju URL adresu, što omogućava napade otvorenog preusmeravanja.
Verovanje korisničkom unosu: Preusmeravanje na URL adrese koje su pružili korisnici bez validacije može dovesti do fišinga, distribucije malvera ili krađe akreditiva.
Kako napadači to zloupotrebljavaju:
Napadači mogu kreirati URL adrese koje izgledaju kao da potiču sa vaše domene, ali preusmeravaju korisnike na zlonamerne sajtove. Na primer:
Izlaganje osetljivih putanja: Aliasiranje osetljivih direktorijuma i omogućavanje pristupa sa klijentske strane može dovesti do curenja poverljivih informacija.
Pakovanje tajni: Ako su osetljivi fajlovi pakovani za klijenta, njihov sadržaj postaje dostupan putem izvornih mapa ili inspekcijom koda sa klijentske strane.
Kako napadači to zloupotrebljavaju:
Napadači mogu pristupiti ili rekonstruisati strukturu direktorijuma aplikacije, potencijalno pronalazeći i koristeći osetljive fajlove ili podatke.
pages/_app.js i pages/_document.js
pages/_app.js
Svrha: Preuzima podrazumevanu App komponentu, omogućavajući globalno stanje, stilove i komponente rasporeda.
Сврха: Док Next.js долази са уграђеним сервером, можете креирати прилагођени сервер за напредне случајеве као што су прилагођено рутирање или интеграција са постојећим позадинским услугама.
Напомена: Користење прилагођеног сервера може ограничити опције распоређивања, посебно на платформама као што је Vercel које оптимизују за уграђени сервер Next.js.
Svrha: Upravljanje osetljivim informacijama i podešavanjima konfiguracije van koda.
Najbolje Prakse:
Koristite .env Fajlove: Čuvajte promenljive poput API ključeva u .env.local (isključeno iz kontrole verzija).
Pristupajte Promenljivim Bezbedno: Koristite process.env.VARIABLE_NAME za pristup promenljivim okruženja.
Nikada ne Izlažite Tajne na Klijentu: Osigurajte da se osetljive promenljive koriste samo na serverskoj strani.
Primer:
// 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},};
Napomena: Da biste ograničili promenljive samo na server, izostavite ih iz env objekta ili ih prefiksirajte sa NEXT_PUBLIC_ za izlaganje klijentu.
Autentifikacija i Autorizacija
Pristup:
Autentifikacija zasnovana na sesiji: Koristite kolačiće za upravljanje korisničkim sesijama.
Autentifikacija zasnovana na tokenima: Implementirajte JWT-ove za stateless autentifikaciju.
Treće strane: Integracija sa OAuth provajderima (npr. Google, GitHub) koristeći biblioteke kao što je next-auth.
Prakse bezbednosti:
Sigurni kolačići: Postavite atribute HttpOnly, Secure i SameSite.
Hashovanje lozinki: Uvek hashujte lozinke pre nego što ih sačuvate.
Validacija unosa: Sprečite napade injekcijom validacijom i sanitizacijom unosa.