Získajte väčšiu kontrolu nad logikou overovania vašej aplikácie Next.js prostredníctvom vlastnej implementácie overovania založenej na JWT.

Autentifikácia pomocou tokenov je populárna stratégia používaná na ochranu webových a mobilných aplikácií pred neoprávneným prístupom. V Next.js môžete využiť autentifikačné funkcie poskytované Next-auth.

Prípadne sa môžete rozhodnúť vyvinúť vlastný autentifikačný systém založený na tokenoch pomocou webových tokenov JSON (JWT). Tým zaistíte, že budete mať väčšiu kontrolu nad logikou autentifikácie; v podstate prispôsobenie systému tak, aby presne zodpovedal požiadavkám vášho projektu.

Nastavte projekt Next.js

Ak chcete začať, nainštalujte Next.js spustením príkazu nižšie na vašom termináli.

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

Tento návod využije Next.js 13, ktorý obsahuje adresár aplikácie.

Ďalej nainštalujte tieto závislosti vo svojom projekte pomocou npm, správca balíkov uzlov.

npm install jose universal-cookie

Jose je modul JavaScript, ktorý poskytuje sadu nástrojov na prácu s webovými tokenmi JSON, zatiaľ čo

instagram viewer
univerzálny súbor cookie závislosť poskytuje jednoduchý spôsob práce so súbormi cookie prehliadača v prostredí na strane klienta aj na strane servera.

Kód tohto projektu nájdete v tomto úložisko GitHub.

Vytvorte používateľské rozhranie prihlasovacieho formulára

Otvor src/aplikácia adresár, vytvorte nový priečinok a pomenujte ho Prihlásiť sa. Do tohto priečinka pridajte nový page.js súbor a zahrňte nižšie uvedený kód.

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

exportdefaultfunctionLoginPage() {
return (


Vyššie uvedený kód vytvorí funkčný komponent prihlasovacej stránky, ktorý v prehliadači vykreslí jednoduchý prihlasovací formulár, ktorý používateľom umožní zadať používateľské meno a heslo.

The používať klienta v kóde zaisťuje, že hranica je deklarovaná medzi kódom iba pre server a iba pre klienta v aplikácie adresár.

V tomto prípade sa používa na deklarovanie, že kód na prihlasovacej stránke, najmä rukoväťOdoslaťfunkcia sa vykonáva iba na klientovi; v opačnom prípade Next.js vyvolá chybu.

Teraz definujme kód pre rukoväťOdoslať funkciu. Do funkčného komponentu pridajte nasledujúci kód.

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

Na správu logiky autentifikácie prihlásenia táto funkcia zachytáva poverenia používateľa z prihlasovacieho formulára. Potom odošle požiadavku POST na koncový bod API, ktorý odovzdá podrobnosti o používateľovi na overenie.

Ak sú poverenia platné, čo znamená, že proces prihlásenia bol úspešný – API vráti v odpovedi stav úspechu. Funkcia obsluhy potom použije smerovač Next.js na navigáciu používateľa na zadanú adresu URL, v tomto prípade chránené trasu.

Definujte koncový bod Login API

Vnútri src/aplikácia adresár, vytvorte nový priečinok a pomenujte ho api. Do tohto priečinka pridajte nový login/route.js súbor a zahrňte nižšie uvedený kód.

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

Primárnou úlohou tohto API je overiť prihlasovacie poverenia odovzdané v požiadavkách POST pomocou falošných údajov.

Po úspešnom overení vygeneruje zašifrovaný token JWT spojený s údajmi overeného používateľa. Nakoniec odošle klientovi úspešnú odpoveď vrátane tokenu v súboroch cookie odpovede; v opačnom prípade vráti odpoveď na stav zlyhania.

Implementujte logiku overenia tokenov

Prvým krokom v autentifikácii tokenu je vygenerovanie tokenu po úspešnom procese prihlásenia. Ďalším krokom je implementácia logiky overovania tokenov.

V podstate budete používať jwtVerify funkciu, ktorú poskytuje Jose modul na overenie odovzdaných tokenov JWT s následnými požiadavkami HTTP.

V src adresár, vytvorte nový libs/auth.js súbor a zahrňte nižšie uvedený kód.

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

Tajný kľúč sa používa na podpisovanie a overovanie tokenov. Porovnaním dekódovaného podpisu tokenu s očakávaným podpisom môže server efektívne overiť, či je poskytnutý token platný, a nakoniec autorizovať požiadavky používateľov.

Vytvorte .env súbor v koreňovom adresári a pridajte jedinečný tajný kľúč takto:

NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key

Vytvorte chránenú trasu

Teraz musíte vytvoriť trasu, ku ktorej môžu získať prístup iba overení používatelia. Ak to chcete urobiť, vytvorte nový protected/page.js súbor v src/aplikácia adresár. Do tohto súboru pridajte nasledujúci kód.

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

Vytvorte Hook na správu stavu overenia

Vytvorte nový priečinok v src adresár a pomenujte ho háčiky. Do tohto priečinka pridajte nový useAuth/index.js súbor a zahrňte nižšie uvedený kód.

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

Tento hák spravuje stav autentifikácie na strane klienta. Načítava a overuje platnosť tokenu JWT prítomného v súboroch cookie pomocou overiťJwtToken a potom nastaví podrobnosti overeného používateľa na auth štát.

Týmto umožňuje ostatným komponentom prístup a využívanie informácií overeného používateľa. Je to nevyhnutné pre scenáre, ako je vykonávanie aktualizácií používateľského rozhrania na základe stavu overenia, následné požiadavky API alebo vykresľovanie odlišného obsahu na základe rolí používateľov.

V tomto prípade použijete hák na vykreslenie iného obsahu na Domov na základe stavu autentifikácie užívateľa.

Alternatívnym prístupom, ktorý by ste mohli zvážiť, je manipulácia riadenie stavu pomocou Redux Toolkit alebo zamestnávanie a nástroj riadenia štátu ako Jotai. Tento prístup zaručuje, že komponenty môžu získať globálny prístup k stavu autentifikácie alebo akémukoľvek inému definovanému stavu.

Pokračujte a otvorte app/page.js súbor, odstráňte štandardný kód Next.js a pridajte nasledujúci kód.

"use client" ;

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

Public Home Page</h1>

Vyššie uvedený kód využíva useAuth háčik na správu stavu overenia. Pritom podmienečne vykreslí verejnú domovskú stránku s odkazom na Prihlásiť sa smerovanie stránky, keď používateľ nie je overený, a zobrazí odsek pre overeného používateľa.

Pridajte middleware na vynútenie autorizovaného prístupu k chráneným trasám

V src adresár, vytvorte nový middleware.js súbor a pridajte kód nižšie.

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*"] };

Tento middleware kód funguje ako strážca. Skontroluje, či používatelia chcú pristupovať k chráneným stránkam, sú overení a autorizovaní na prístup k trasám, okrem toho, že presmerováva neoprávnených používateľov na prihlasovaciu stránku.

Zabezpečenie aplikácií Next.js

Autentifikácia pomocou tokenov je účinný bezpečnostný mechanizmus. Nie je to však jediná dostupná stratégia na ochranu vašich aplikácií pred neoprávneným prístupom.

Na posilnenie aplikácií proti dynamickému prostrediu kybernetickej bezpečnosti je dôležité prijať komplexné zabezpečenie prístup, ktorý holisticky rieši potenciálne bezpečnostné medzery a slabé miesta, aby zaručil dôkladnosť ochranu.