Vairāk kontrolējiet savas lietotnes Next.js autentifikācijas loģiku, izmantojot pielāgotu JWT autentifikācijas ieviešanu.

Tokena autentifikācija ir populāra stratēģija, ko izmanto, lai aizsargātu tīmekļa un mobilās lietojumprogrammas no nesankcionētas piekļuves. Vietnē Next.js varat izmantot Next-auth nodrošinātās autentifikācijas funkcijas.

Varat arī izvēlēties izstrādāt pielāgotu uz marķieri balstītu autentifikācijas sistēmu, izmantojot JSON tīmekļa marķierus (JWT). To darot, jūs nodrošināsiet lielāku kontroli pār autentifikācijas loģiku; būtībā sistēmas pielāgošana, lai tā precīzi atbilstu jūsu projekta prasībām.

Iestatiet Next.js projektu

Lai sāktu, instalējiet Next.js, savā terminālī izpildot tālāk norādīto komandu.

npx create-next-app@latest next-auth-jwt --experimental-app

Šī rokasgrāmata izmantos Next.js 13, kas ietver lietotņu direktoriju.

Pēc tam instalējiet šīs atkarības savā projektā, izmantojot npm, mezgla pakotņu pārvaldnieks.

npm install jose universal-cookie

Hosē ir JavaScript modulis, kas nodrošina utilītu kopu darbam ar JSON tīmekļa marķieriem, kamēr

universāls cepums atkarība nodrošina vienkāršu veidu, kā strādāt ar pārlūkprogrammas sīkfailiem gan klienta, gan servera vidē.

Jūs varat atrast šī projekta kodu GitHub repozitorijs.

Izveidojiet pieteikšanās veidlapas lietotāja interfeisu

Atveriet src/app direktorijā, izveidojiet jaunu mapi un piešķiriet tai nosaukumu Pieslēgties. Šajā mapē pievienojiet jaunu page.js failu un iekļaujiet tālāk norādīto kodu.

"use client";
import { useRouter } from"next/navigation";

exportdefaultfunctionLoginPage() {
return (


Iepriekš minētais kods izveido pieteikšanās lapas funkcionālo komponentu, kas pārlūkprogrammā atveidos vienkāršu pieteikšanās veidlapu, lai lietotāji varētu ievadīt lietotājvārdu un paroli.

The izmantot klientu paziņojums kodā nodrošina, ka tiek deklarēta robeža starp tikai servera un tikai klienta kodu lietotne direktoriju.

Šajā gadījumā tas tiek izmantots, lai paziņotu, ka kods pieteikšanās lapā, jo īpaši, rokturisIesniegtfunkcija tiek izpildīta tikai klientam; pretējā gadījumā Next.js parādīs kļūdu.

Tagad definēsim kodu rokturisIesniegt funkciju. Funkcionālā komponenta iekšpusē pievienojiet šādu kodu.

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");
}
 };

Lai pārvaldītu pieteikšanās autentifikācijas loģiku, šī funkcija tver lietotāja akreditācijas datus no pieteikšanās veidlapas. Pēc tam tas nosūta POST pieprasījumu API galapunktam, nododot lietotāja informāciju pārbaudei.

Ja akreditācijas dati ir derīgi, tas norāda, ka pieteikšanās process bija veiksmīgs — API atbildē atgriež veiksmīgas statusu. Apdarinātāja funkcija pēc tam izmantos Next.js maršrutētāju, lai pārvietotu lietotāju uz noteiktu URL, šajā gadījumā aizsargāts maršruts.

Definējiet pieteikšanās API galapunktu

Iekšpusē src/app direktorijā, izveidojiet jaunu mapi un piešķiriet tai nosaukumu api. Šajā mapē pievienojiet jaunu login/route.js failu un iekļaujiet tālāk norādīto kodu.

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 });
}

Šīs API galvenais uzdevums ir pārbaudīt pieteikšanās akreditācijas datus, kas nodoti POST pieprasījumos, izmantojot viltotus datus.

Pēc veiksmīgas pārbaudes tas ģenerē šifrētu JWT marķieri, kas saistīts ar autentificēta lietotāja informāciju. Visbeidzot, tas nosūta klientam veiksmīgu atbildi, tostarp atbildes sīkfailos esošo marķieri; pretējā gadījumā tas atgriež atbildi par kļūmes statusu.

Ieviesiet marķiera verifikācijas loģiku

Sākotnējais pilnvaras autentifikācijas solis ir marķiera ģenerēšana pēc veiksmīga pieteikšanās procesa. Nākamais solis ir ieviest marķiera verifikācijas loģiku.

Būtībā jūs izmantosit jwtPārbaudīt funkcija, ko nodrošina Hosē modulis, lai pārbaudītu JWT marķierus, kas nodoti ar nākamajiem HTTP pieprasījumiem.

Iekš src direktorijā, izveidojiet jaunu libs/auth.js failu un iekļaujiet tālāk norādīto kodu.

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;
}
}

Slepenā atslēga tiek izmantota žetonu parakstīšanai un pārbaudei. Salīdzinot dekodētā marķiera parakstu ar paredzamo parakstu, serveris var efektīvi pārbaudīt, vai nodrošinātais marķieris ir derīgs, un galu galā autorizēt lietotāju pieprasījumus.

Izveidot .env failu saknes direktorijā un pievienojiet unikālu slepeno atslēgu šādi:

NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key

Izveidojiet aizsargātu maršrutu

Tagad jums ir jāizveido maršruts, kuram var piekļūt tikai autentificēti lietotāji. Lai to izdarītu, izveidojiet jaunu Protected/page.js failu mapē src/app direktoriju. Šajā failā pievienojiet šādu kodu.

exportdefaultfunctionProtectedPage() {
return<h1>Very protected pageh1>;
}

Izveidojiet āķi, lai pārvaldītu autentifikācijas stāvokli

Izveidojiet jaunu mapi mapē src direktoriju un nosauciet to āķi. Šajā mapē pievienojiet jaunu useAuth/index.js failu un iekļaujiet tālāk norādīto kodu.

"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 āķis pārvalda autentifikācijas stāvokli klienta pusē. Tas ienes un pārbauda sīkfailos esošā JWT marķiera derīgumu, izmantojot verifyJwtToken funkciju un pēc tam iestata autentificēta lietotāja informāciju uz aut Valsts.

To darot, tas ļauj citiem komponentiem piekļūt un izmantot autentificētā lietotāja informāciju. Tas ir būtiski tādiem scenārijiem kā lietotāja saskarnes atjauninājumu veikšana, pamatojoties uz autentifikācijas statusu, turpmāku API pieprasījumu veikšana vai dažāda satura renderēšana, pamatojoties uz lietotāju lomām.

Šajā gadījumā jūs izmantosit āķi, lai atveidotu atšķirīgu saturu mājas maršruts, pamatojoties uz lietotāja autentifikācijas stāvokli.

Alternatīva pieeja, ko jūs varētu apsvērt, ir apstrāde stāvokļa pārvaldība, izmantojot Redux Toolkit vai nodarbina a valsts pārvaldības rīks, piemēram, Jotai. Šī pieeja garantē, ka komponenti var iegūt globālu piekļuvi autentifikācijas stāvoklim vai jebkuram citam noteiktam stāvoklim.

Iet uz priekšu un atveriet app/page.js failu, izdzēsiet standarta Next.js kodu un pievienojiet šādu kodu.

"use client" ;

import { useAuth } from"@/hooks/useAuth";
import Link from"next/link";
exportdefaultfunctionHome() {
const auth = useAuth();
return<>

Public Home Page</h1>

Iepriekš minētais kods izmanto useAuth āķis, lai pārvaldītu autentifikācijas stāvokli. To darot, tas nosacīti veido publisku sākumlapu ar saiti uz Pieslēgties lapas maršruts, kad lietotājs nav autentificēts, un parāda rindkopu autentificētam lietotājam.

Pievienojiet starpprogrammatūru, lai nodrošinātu autorizētu piekļuvi aizsargātiem maršrutiem

Iekš src direktorijā, izveidojiet jaunu starpprogrammatūra.js failu un pievienojiet tālāk norādīto kodu.

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 starpprogrammatūras kods darbojas kā aizsargs. Tā pārbauda, ​​vai tad, kad lietotāji vēlas piekļūt aizsargātām lapām, viņi ir autentificēti un pilnvaroti piekļūt maršrutiem, kā arī novirza neautorizētus lietotājus uz pieteikšanās lapu.

Next.js lietojumprogrammu nodrošināšana

Token autentifikācija ir efektīvs drošības mehānisms. Tomēr tā nav vienīgā pieejamā stratēģija, lai aizsargātu jūsu lietojumprogrammas no nesankcionētas piekļuves.

Lai stiprinātu lietojumprogrammas pret dinamisko kiberdrošības vidi, ir svarīgi pieņemt visaptverošu drošību pieeja, kas holistiski novērš iespējamās drošības nepilnības un ievainojamības, lai garantētu rūpīgu aizsardzība.