Naudodami tinkintą JWT pagrįstą autentifikavimo diegimą geriau valdykite Next.js programos autentifikavimo logiką.
Žetonų autentifikavimas yra populiari strategija, naudojama siekiant apsaugoti žiniatinklio ir mobiliąsias programas nuo neteisėtos prieigos. „Next.js“ galite naudoti „Next-auth“ teikiamas autentifikavimo funkcijas.
Arba galite pasirinkti sukurti tinkintą prieigos raktu pagrįstą autentifikavimo sistemą naudodami JSON žiniatinklio prieigos raktus (JWT). Tai darydami užtikrinate, kad galėsite geriau valdyti autentifikavimo logiką; iš esmės pritaikyti sistemą, kad ji tiksliai atitiktų jūsų projekto reikalavimus.
Sukurkite Next.js projektą
Norėdami pradėti, įdiekite Next.js vykdydami toliau pateiktą komandą savo terminale.
npx create-next-app@latest next-auth-jwt --experimental-app
Šis vadovas bus naudojamas Next.js 13, kuriame yra programų katalogas.
Tada įdiekite šias priklausomybes savo projekte naudodami npm, mazgo paketų tvarkyklė.
npm install jose universal-cookie
Jose yra „JavaScript“ modulis, kuriame pateikiamas paslaugų rinkinys, skirtas darbui su JSON žiniatinklio prieigos raktais
universalus-slapukas priklausomybė suteikia paprastą būdą dirbti su naršyklės slapukais tiek kliento, tiek serverio aplinkoje.Šio projekto kodą rasite čia GitHub saugykla.
Sukurkite prisijungimo formos vartotojo sąsają
Atidaryk src/app kataloge, sukurkite naują aplanką ir pavadinkite jį Prisijungti. Šiame aplanke pridėkite naują page.js failą ir įtraukite žemiau esantį kodą.
"use client";
import { useRouter } from"next/navigation";
exportdefaultfunctionLoginPage() {
return (
Aukščiau pateiktas kodas sukuria prisijungimo puslapio funkcinį komponentą, kuris naršyklėje pateiks paprastą prisijungimo formą, kad vartotojai galėtų įvesti vartotojo vardą ir slaptažodį.
The naudoti klientą teiginys kode užtikrina, kad riba tarp tik serverio ir tik klientui skirto kodo būtų deklaruota programėlė katalogas.
Šiuo atveju jis naudojamas deklaruoti, kad prisijungimo puslapyje esantis kodas, ypač rankenaPateiktifunkcija vykdoma tik klientui; kitu atveju Next.js išmes klaidą.
Dabar apibrėžkime kodą rankenaPateikti funkcija. Funkcinio komponento viduje pridėkite šį 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");
}
};
Norint valdyti prisijungimo autentifikavimo logiką, ši funkcija fiksuoja vartotojo kredencialus iš prisijungimo formos. Tada jis siunčia POST užklausą į API galutinį tašką, perduodamas vartotojo informaciją patvirtinimui.
Jei kredencialai galioja, tai reiškia, kad prisijungimo procesas buvo sėkmingas – API atsakyme grąžina sėkmingą būseną. Tada tvarkyklės funkcija naudos Next.js maršrutizatorių, kad nukreiptų vartotoją į nurodytą URL, šiuo atveju apsaugotas maršrutą.
Apibrėžkite prisijungimo API galinį tašką
Viduje src/app kataloge, sukurkite naują aplanką ir pavadinkite jį api. Šiame aplanke pridėkite naują login/route.js failą ir įtraukite žemiau esantį kodą.
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 });
}
Pagrindinė šios API užduotis yra patikrinti prisijungimo kredencialus, perduodamus POST užklausose, naudojant netikrus duomenis.
Sėkmingai patvirtinus, jis sugeneruoja užšifruotą JWT prieigos raktą, susietą su autentifikuoto vartotojo informacija. Galiausiai jis siunčia sėkmingą atsakymą klientui, įskaitant atsakymo slapukuose esantį prieigos raktą; kitu atveju jis grąžina atsaką į gedimo būseną.
Įdiekite žetonų patvirtinimo logiką
Pradinis prieigos rakto autentifikavimo veiksmas yra prieigos rakto generavimas po sėkmingo prisijungimo proceso. Kitas žingsnis yra žetonų patvirtinimo logikos įgyvendinimas.
Iš esmės jūs naudosite jwtPatvirtinti teikiama funkcija Jose modulis, skirtas patikrinti JWT prieigos raktus, perduodamus su vėlesnėmis HTTP užklausomis.
Viduje src katalogą, sukurkite naują libs/auth.js failą ir įtraukite žemiau esantį kodą.
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;
}
}
Slaptasis raktas naudojamas pasirašant ir tikrinant žetonus. Palygindamas iššifruotą prieigos rakto parašą su laukiamu parašu, serveris gali veiksmingai patikrinti, ar pateiktas prieigos raktas galioja, ir galiausiai patvirtinti vartotojų užklausas.
Sukurti .env failą šakniniame kataloge ir pridėkite unikalų slaptąjį raktą taip:
NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key
Sukurkite saugomą maršrutą
Dabar turite sukurti maršrutą, prie kurio galėtų patekti tik autentifikuoti vartotojai. Norėdami tai padaryti, sukurkite naują Protected/page.js failą src/app katalogas. Šiame faile pridėkite šį kodą.
exportdefaultfunctionProtectedPage() {
return<h1>Very protected pageh1>;
}
Sukurkite kabliuką autentifikavimo būsenai valdyti
Sukurkite naują aplanką src katalogą ir pavadinkite jį kabliukai. Šiame aplanke pridėkite naują useAuth/index.js failą ir įtraukite žemiau esantį kodą.
"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;
}
Šis kabliukas valdo autentifikavimo būseną kliento pusėje. Jis paima ir patikrina JWT prieigos rakto, esančio slapukuose, galiojimą naudodamas VerifyJwtToken funkcija, tada nustato autentifikuoto vartotojo duomenis į aut valstybė.
Tai leidžia kitiems komponentams pasiekti ir naudoti autentifikuoto vartotojo informaciją. Tai būtina tokiais atvejais, kaip NS naujinimai pagal autentifikavimo būseną, vėlesnių API užklausų pateikimas arba skirtingo turinio pateikimas pagal vartotojo vaidmenis.
Tokiu atveju naudosite kabliuką, kad pateiktumėte skirtingą turinį namai maršrutas, pagrįstas vartotojo autentifikavimo būsena.
Alternatyvus būdas, kurį galite apsvarstyti, yra tvarkymas būsenos valdymas naudojant Redux Toolkit arba samdantis a valstybės valdymo įrankis kaip Jotai. Šis metodas garantuoja, kad komponentai gali gauti visuotinę prieigą prie autentifikavimo būsenos arba bet kurios kitos apibrėžtos būsenos.
Eikite į priekį ir atidarykite app/page.js failą, ištrinkite Next.js kodą ir pridėkite šį kodą.
"use client" ;
import { useAuth } from"@/hooks/useAuth";
import Link from"next/link";
exportdefaultfunctionHome() {
const auth = useAuth();
return<>Public Home Page</h1>
Aukščiau pateiktas kodas naudoja useAuth kabliukas autentifikavimo būsenai valdyti. Tai darydamas, jis sąlyginai pateikia viešą pagrindinį puslapį su nuoroda į Prisijungti puslapio maršrutą, kai vartotojas nėra autentifikuotas, ir rodo autentifikuoto vartotojo pastraipą.
Pridėkite tarpinę programinę įrangą, kad užtikrintumėte įgaliotą prieigą prie saugomų maršrutų
Viduje src katalogą, sukurkite naują tarpinė programinė įranga.js failą ir pridėkite toliau esantį kodą.
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*"] };
Šis tarpinės programinės įrangos kodas veikia kaip apsauga. Ji tikrina, kad vartotojai, norintys pasiekti apsaugotus puslapius, būtų autentifikuoti ir įgalioti pasiekti maršrutus, be to, neleistini naudotojai nukreipiami į prisijungimo puslapį.
„Next.js“ programų apsauga
Žetonų autentifikavimas yra veiksmingas apsaugos mechanizmas. Tačiau tai nėra vienintelė strategija, skirta apsaugoti programas nuo neteisėtos prieigos.
Norint sustiprinti programas nuo dinamiško kibernetinio saugumo kraštovaizdžio, svarbu įdiegti visapusišką saugumą požiūris, kuris visapusiškai pašalina galimas saugumo spragas ir pažeidžiamumą, kad būtų užtikrintas išsamus apsauga.