Imajte veću kontrolu nad logikom provjere autentičnosti svoje aplikacije Next.js putem prilagođene implementacije provjere autentičnosti temeljene na JWT-u.
Provjera autentičnosti tokenom popularna je strategija koja se koristi u zaštiti web i mobilnih aplikacija od neovlaštenog pristupa. U Next.js možete koristiti značajke provjere autentičnosti koje nudi Next-auth.
Alternativno, možete se odlučiti za razvoj prilagođenog sustava provjere autentičnosti koji se temelji na tokenu pomoću JSON web tokena (JWT). Na taj način osiguravate veću kontrolu nad logikom provjere autentičnosti; u suštini, prilagođavanje sustava kako bi točno odgovarao zahtjevima vašeg projekta.
Postavite Next.js projekt
Za početak instalirajte Next.js pokretanjem donje naredbe na svom terminalu.
npx create-next-app@latest next-auth-jwt --experimental-app
Ovaj će vodič koristiti Next.js 13 koji uključuje direktorij aplikacije.
Zatim instalirajte ove ovisnosti u svoj projekt pomoću npm, upravitelj paketa čvora.
npm install jose universal-cookie
Jose je JavaScript modul koji pruža skup uslužnih programa za rad s JSON web tokenima dok univerzalni kolačić ovisnost pruža jednostavan način rada s kolačićima preglednika u okruženjima na strani klijenta i na strani poslužitelja.
Kôd ovog projekta možete pronaći ovdje GitHub spremište.
Napravite korisničko sučelje obrasca za prijavu
Otvori src/aplikacija imenik, stvorite novu mapu i dajte joj naziv prijaviti se. Unutar ove mape dodajte novu stranica.js datoteku i uključite kod u nastavku.
"use client";
import { useRouter } from"next/navigation";
exportdefaultfunctionLoginPage() {
return (
Gornji kod stvara funkcionalnu komponentu stranice za prijavu koja će prikazati jednostavan obrazac za prijavu u pregledniku kako bi korisnicima omogućila unos korisničkog imena i lozinke.
The koristiti klijenta izjava u kodu osigurava da je deklarirana granica između koda samo za poslužitelj i samo za klijenta u aplikacija imenik.
U ovom slučaju, koristi se za deklaraciju da je kod na stranici za prijavu, posebno rukovanjePošaljifunkcija se izvršava samo na klijentu; inače će Next.js izbaciti pogrešku.
Sada definirajmo kod za rukovanjePošalji funkcija. Unutar funkcionalne komponente dodajte sljedeći kod.
const router = useRouter();
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const username = formData.get("username");
const password = formData.get("password");
const res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify({ username, password }),
});
const { success } = await res.json();
if (success) {
router.push("/protected");
router.refresh();
} else {
alert("Login failed");
}
};
Za upravljanje logikom provjere autentičnosti prijave, ova funkcija bilježi korisničke vjerodajnice iz obrasca za prijavu. Zatim šalje POST zahtjev API krajnjoj točki prosljeđujući korisničke podatke za provjeru.
Ako su vjerodajnice valjane, što znači da je postupak prijave bio uspješan—API u odgovoru vraća status uspjeha. Funkcija obrađivača zatim će koristiti usmjerivač Next.js za navigaciju korisnika do određenog URL-a, u ovom slučaju, zaštićen ruta.
Definirajte krajnju točku API-ja za prijavu
Unutar src/aplikacija imenik, stvorite novu mapu i dajte joj naziv api. Unutar ove mape dodajte novu prijava/ruta.js datoteku i uključite kod u nastavku.
import { SignJWT } from"jose";
import { NextResponse } from"next/server";
import { getJwtSecretKey } from"@/libs/auth";
exportasyncfunctionPOST(request) {
const body = await request.json();
if (body.username "admin" && body.password "admin") {
const token = awaitnew SignJWT({
username: body.username,
})
.setProtectedHeader({ alg: "HS256" })
.setIssuedAt()
.setExpirationTime("30s")
.sign(getJwtSecretKey());
const response = NextResponse.json(
{ success: true },
{ status: 200, headers: { "content-type": "application/json" } }
);
response.cookies.set({
name: "token",
value: token,
path: "/",
});
return response;
}
return NextResponse.json({ success: false });
}
Primarni zadatak ovog API-ja je provjera vjerodajnica za prijavu proslijeđenih u POST zahtjevima pomoću lažnih podataka.
Nakon uspješne provjere, generira šifrirani JWT token povezan s pojedinostima autentificiranog korisnika. Konačno, šalje uspješan odgovor klijentu, uključujući token u kolačićima odgovora; inače vraća odgovor o statusu greške.
Implementirajte logiku provjere tokena
Početni korak u autentifikaciji tokena je generiranje tokena nakon uspješnog procesa prijave. Sljedeći korak je implementacija logike za provjeru tokena.
U biti ćete koristiti jwtVerify funkcija koju pruža Jose modul za provjeru JWT tokena proslijeđenih s naknadnim HTTP zahtjevima.
u src imenik, stvorite novi libs/auth.js datoteku i uključite kod u nastavku.
import { jwtVerify } from"jose";
exportfunctiongetJwtSecretKey() {
const secret = process.env.NEXT_PUBLIC_JWT_SECRET_KEY;
if (!secret) {
thrownewError("JWT Secret key is not matched");
}
returnnew TextEncoder().encode(secret);
}
exportasyncfunctionverifyJwtToken(token) {
try {
const { payload } = await jwtVerify(token, getJwtSecretKey());
return payload;
} catch (error) {
returnnull;
}
}
Tajni ključ se koristi za potpisivanje i provjeru tokena. Uspoređujući dekodirani potpis tokena s očekivanim potpisom, poslužitelj može učinkovito provjeriti je li dostavljeni token valjan i na kraju autorizirati zahtjeve korisnika.
Stvoriti .env datoteku u korijenskom direktoriju i dodajte jedinstveni tajni ključ na sljedeći način:
NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key
Stvorite zaštićenu rutu
Sada morate stvoriti rutu kojoj samo autentificirani korisnici mogu pristupiti. Da biste to učinili, stvorite novi zaštićeno/stranica.js datoteka u src/aplikacija imenik. Unutar ove datoteke dodajte sljedeći kod.
exportdefaultfunctionProtectedPage() {
return<h1>Very protected pageh1>;
}
Stvorite kuku za upravljanje stanjem autentifikacije
Stvorite novu mapu u src imenik i nazovite ga udice. Unutar ove mape dodajte novu useAuth/index.js datoteku i uključite kod u nastavku.
"use client" ;
import React from"react";
import Cookies from"universal-cookie";
import { verifyJwtToken } from"@/libs/auth";exportfunctionuseAuth() {
const [auth, setAuth] = React.useState(null);
const getVerifiedtoken = async () => {
const cookies = new Cookies();
const token = cookies.get("token")?? null;
const verifiedToken = await verifyJwtToken(token);
setAuth(verifiedToken);
};
React.useEffect(() => {
getVerifiedtoken();
}, []);
return auth;
}
Ova kuka upravlja stanjem provjere autentičnosti na strani klijenta. Dohvaća i provjerava valjanost JWT tokena prisutnog u kolačićima pomoću provjeriJwtToken funkciju, a zatim postavlja pojedinosti provjerenog korisnika na auth država.
Čineći to, dopušta drugim komponentama da pristupe i iskoriste informacije autentificiranog korisnika. Ovo je bitno za scenarije poput ažuriranja korisničkog sučelja na temelju statusa provjere autentičnosti, upućivanja naknadnih API zahtjeva ili prikazivanja različitog sadržaja na temelju korisničkih uloga.
U ovom slučaju, upotrijebit ćete kuku za prikaz različitog sadržaja na Dom ruta na temelju stanja provjere autentičnosti korisnika.
Alternativni pristup koji biste mogli razmotriti je rukovanje upravljanje stanjem pomoću Redux Toolkita ili zapošljavanje a alat za upravljanje državom poput Jotaija. Ovaj pristup jamči da komponente mogu dobiti globalni pristup stanju provjere autentičnosti ili bilo kojem drugom definiranom stanju.
Samo naprijed i otvori aplikacija/stranica.js datoteku, izbrišite predložak Next.js koda i dodajte sljedeći kod.
"use client" ;
import { useAuth } from"@/hooks/useAuth";
import Link from"next/link";
exportdefaultfunctionHome() {
const auth = useAuth();
return<>Public Home Page</h1>
Gornji kod koristi useAuth kuka za upravljanje stanjem provjere autentičnosti. Pritom uvjetno prikazuje javnu početnu stranicu s vezom na prijaviti se ruta stranice kada korisnik nije autentificiran i prikazuje odlomak za autentificiranog korisnika.
Dodajte Middleware za nametanje ovlaštenog pristupa zaštićenim rutama
u src imenik, stvorite novi međuprogram.js datoteku i dodajte kod u nastavku.
import { NextResponse } from"next/server";
import { verifyJwtToken } from"@/libs/auth";const AUTH_PAGES = ["/login"];
const isAuthPages = (url) => AUTH_PAGES.some((page) => page.startsWith(url));
exportasyncfunctionmiddleware(request) {
const { url, nextUrl, cookies } = request;
const { value: token } = cookies.get("token")?? { value: null };
const hasVerifiedToken = token && (await verifyJwtToken(token));
const isAuthPageRequested = isAuthPages(nextUrl.pathname);if (isAuthPageRequested) {
if (!hasVerifiedToken) {
const response = NextResponse.next();
response.cookies.delete("token");
return response;
}
const response = NextResponse.redirect(new URL(`/`, url));
return response;
}if (!hasVerifiedToken) {
const searchParams = new URLSearchParams(nextUrl.searchParams);
searchParams.set("next", nextUrl.pathname);
const response = NextResponse.redirect(
new URL(`/login?${searchParams}`, url)
);
response.cookies.delete("token");
return response;
}return NextResponse.next();
}
exportconst config = { matcher: ["/login", "/protected/:path*"] };
Ovaj međuprogramski kod djeluje kao čuvar. Provjerava da li su korisnici, kada žele pristupiti zaštićenim stranicama, autentificirani i ovlašteni za pristup rutama, uz preusmjeravanje neovlaštenih korisnika na stranicu za prijavu.
Zaštita Next.js aplikacija
Autentifikacija tokenom učinkovit je sigurnosni mehanizam. Međutim, to nije jedina dostupna strategija za zaštitu vaših aplikacija od neovlaštenog pristupa.
Za jačanje aplikacija protiv dinamičnog okruženja kibernetičke sigurnosti važno je usvojiti sveobuhvatnu sigurnost pristup koji holistički rješava potencijalne sigurnosne rupe i ranjivosti kako bi se zajamčila temeljita zaštita.