Έχετε περισσότερο έλεγχο στη λογική ελέγχου ταυτότητας της εφαρμογής Next.js μέσω προσαρμοσμένης εφαρμογής ελέγχου ταυτότητας που βασίζεται σε JWT.

Ο έλεγχος ταυτότητας με διακριτικό είναι μια δημοφιλής στρατηγική που χρησιμοποιείται για την προστασία εφαρμογών ιστού και κινητών από μη εξουσιοδοτημένη πρόσβαση. Στο Next.js, μπορείτε να χρησιμοποιήσετε τις δυνατότητες ελέγχου ταυτότητας που παρέχονται από το Next-auth.

Εναλλακτικά, μπορείτε να επιλέξετε να αναπτύξετε ένα προσαρμοσμένο σύστημα ελέγχου ταυτότητας που βασίζεται σε διακριτικά χρησιμοποιώντας JSON Web Tokens (JWT). Με αυτόν τον τρόπο, διασφαλίζετε ότι έχετε περισσότερο έλεγχο στη λογική ελέγχου ταυτότητας. ουσιαστικά, προσαρμόζοντας το σύστημα ώστε να ταιριάζει με ακρίβεια στις απαιτήσεις του έργου σας.

Ρύθμιση ενός έργου Next.js

Για να ξεκινήσετε, εγκαταστήστε το Next.js εκτελώντας την παρακάτω εντολή στο τερματικό σας.

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

Αυτός ο οδηγός θα χρησιμοποιηθεί Next.js 13 που περιλαμβάνει τον κατάλογο εφαρμογών.

instagram viewer

Στη συνέχεια, εγκαταστήστε αυτές τις εξαρτήσεις στο έργο σας χρησιμοποιώντας npm, το Node Package Manager.

npm install jose universal-cookie

Χοσέ είναι μια λειτουργική μονάδα JavaScript που παρέχει ένα σύνολο βοηθητικών προγραμμάτων για εργασία με JSON Web Tokens ενώ η universal-cookie Η εξάρτηση παρέχει έναν απλό τρόπο εργασίας με τα cookies του προγράμματος περιήγησης τόσο στο περιβάλλον του πελάτη όσο και στο περιβάλλον του διακομιστή.

Μπορείτε να βρείτε τον κωδικό αυτού του έργου σε αυτό Αποθετήριο GitHub.

Δημιουργήστε τη διεπαφή χρήστη της φόρμας σύνδεσης

Ανοιξε το src/app κατάλογο, δημιουργήστε έναν νέο φάκελο και ονομάστε τον Σύνδεση. Μέσα σε αυτόν τον φάκελο, προσθέστε έναν νέο page.js αρχείο και συμπεριλάβετε τον παρακάτω κώδικα.

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

exportdefaultfunctionLoginPage() {
return (


Ο παραπάνω κώδικας δημιουργεί ένα λειτουργικό στοιχείο σελίδας σύνδεσης που θα αποδώσει μια απλή φόρμα σύνδεσης στο πρόγραμμα περιήγησης που θα επιτρέπει στους χρήστες να εισάγουν ένα όνομα χρήστη και έναν κωδικό πρόσβασης.

ο χρήση πελάτη Η δήλωση στον κώδικα διασφαλίζει ότι δηλώνεται ένα όριο μεταξύ κώδικα μόνο για διακομιστή και κώδικα μόνο για πελάτη στο εφαρμογή Ευρετήριο.

Σε αυτήν την περίπτωση, χρησιμοποιείται για να δηλώσει ότι ο κώδικας στη σελίδα σύνδεσης, ιδιαίτερα, το handleSubmitΗ λειτουργία εκτελείται μόνο στον πελάτη. Διαφορετικά, το Next.js θα εμφανίσει ένα σφάλμα.

Τώρα, ας ορίσουμε τον κώδικα για το handleSubmit λειτουργία. Μέσα στο λειτουργικό στοιχείο, προσθέστε τον ακόλουθο κώδικα.

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

Για τη διαχείριση της λογικής ελέγχου ταυτότητας σύνδεσης, αυτή η συνάρτηση καταγράφει τα διαπιστευτήρια χρήστη από τη φόρμα σύνδεσης. Στη συνέχεια στέλνει ένα αίτημα POST σε ένα τελικό σημείο API περνώντας μαζί με τα στοιχεία του χρήστη για επαλήθευση.

Εάν τα διαπιστευτήρια είναι έγκυρα, υποδεικνύοντας ότι η διαδικασία σύνδεσης ήταν επιτυχής—το API επιστρέφει μια κατάσταση επιτυχίας στην απόκριση. Στη συνέχεια, η συνάρτηση χειριστή θα χρησιμοποιήσει το δρομολογητή Next.js για να πλοηγήσει τον χρήστη σε μια καθορισμένη διεύθυνση URL, σε αυτήν την περίπτωση, το προστατεύονται Διαδρομή.

Καθορίστε το τελικό σημείο σύνδεσης API

μεσα στην src/app κατάλογο, δημιουργήστε έναν νέο φάκελο και ονομάστε τον api. Μέσα σε αυτόν τον φάκελο, προσθέστε έναν νέο login/route.js αρχείο και συμπεριλάβετε τον παρακάτω κώδικα.

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

Το πρωταρχικό καθήκον για αυτό το API είναι να επαληθεύσει τα διαπιστευτήρια σύνδεσης που περνούν στα αιτήματα POST χρησιμοποιώντας εικονικά δεδομένα.

Μετά την επιτυχή επαλήθευση, δημιουργεί ένα κρυπτογραφημένο διακριτικό JWT που σχετίζεται με τα στοιχεία ελέγχου ταυτότητας χρήστη. Τέλος, στέλνει μια επιτυχημένη απάντηση στον πελάτη, συμπεριλαμβανομένου του διακριτικού στα cookies απάντησης. Διαφορετικά, επιστρέφει μια απάντηση κατάστασης αποτυχίας.

Εφαρμόστε τη λογική επαλήθευσης διακριτικού

Το αρχικό βήμα στον έλεγχο ταυτότητας διακριτικού είναι η δημιουργία του διακριτικού μετά από μια επιτυχημένη διαδικασία σύνδεσης. Το επόμενο βήμα είναι να εφαρμόσετε τη λογική για την επαλήθευση διακριτικών.

Ουσιαστικά, θα χρησιμοποιήσετε το jwtΕπαλήθευση λειτουργία που παρέχεται από το Χοσέ μονάδα για την επαλήθευση των κουπονιών JWT που έχουν περάσει με επόμενα αιτήματα HTTP.

Στο src κατάλογο, δημιουργήστε ένα νέο libs/auth.js αρχείο και συμπεριλάβετε τον παρακάτω κώδικα.

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

Το μυστικό κλειδί χρησιμοποιείται για την υπογραφή και την επαλήθευση των διακριτικών. Συγκρίνοντας την αποκωδικοποιημένη υπογραφή διακριτικού με την αναμενόμενη υπογραφή, ο διακομιστής μπορεί να επαληθεύσει αποτελεσματικά ότι το παρεχόμενο διακριτικό είναι έγκυρο και, τελικά, να εξουσιοδοτήσει τα αιτήματα των χρηστών.

Δημιουργώ .env αρχείο στον ριζικό κατάλογο και προσθέστε ένα μοναδικό μυστικό κλειδί ως εξής:

NEXT_PUBLIC_JWT_SECRET_KEY=your_secret_key

Δημιουργήστε μια προστατευμένη διαδρομή

Τώρα, πρέπει να δημιουργήσετε μια διαδρομή στην οποία θα μπορούν να έχουν πρόσβαση μόνο οι πιστοποιημένοι χρήστες. Για να το κάνετε αυτό, δημιουργήστε ένα νέο προστατευμένο/page.js αρχείο στο src/app Ευρετήριο. Μέσα σε αυτό το αρχείο, προσθέστε τον ακόλουθο κώδικα.

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

Δημιουργήστε ένα άγκιστρο για τη διαχείριση της κατάστασης ελέγχου ταυτότητας

Δημιουργήστε έναν νέο φάκελο στο src κατάλογο και ονομάστε τον αγκίστρια. Μέσα σε αυτόν τον φάκελο προσθέστε ένα νέο useAuth/index.js αρχείο και συμπεριλάβετε τον παρακάτω κώδικα.

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

Αυτό το άγκιστρο διαχειρίζεται την κατάσταση ελέγχου ταυτότητας στην πλευρά του πελάτη. Ανακτά και επαληθεύει την εγκυρότητα του διακριτικού JWT που υπάρχει στα cookies χρησιμοποιώντας το verifyJwtToken λειτουργία και, στη συνέχεια, ορίζει τα στοιχεία ελέγχου ταυτότητας χρήστη στο auth κατάσταση.

Με αυτόν τον τρόπο, επιτρέπει σε άλλα στοιχεία να έχουν πρόσβαση και να χρησιμοποιούν τις πληροφορίες του πιστοποιημένου χρήστη. Αυτό είναι απαραίτητο για σενάρια όπως η πραγματοποίηση ενημερώσεων διεπαφής χρήστη με βάση την κατάσταση ελέγχου ταυτότητας, η υποβολή επακόλουθων αιτημάτων API ή η απόδοση διαφορετικού περιεχομένου με βάση τους ρόλους των χρηστών.

Σε αυτήν την περίπτωση, θα χρησιμοποιήσετε το άγκιστρο για να αποδώσετε διαφορετικό περιεχόμενο στο Σπίτι διαδρομή με βάση την κατάσταση ελέγχου ταυτότητας ενός χρήστη.

Μια εναλλακτική προσέγγιση που μπορείτε να εξετάσετε είναι ο χειρισμός διαχείριση κατάστασης με χρήση Redux Toolkit ή απασχολώντας α εργαλείο κρατικής διαχείρισης όπως το Jotai. Αυτή η προσέγγιση εγγυάται ότι τα στοιχεία μπορούν να αποκτήσουν καθολική πρόσβαση στην κατάσταση ελέγχου ταυτότητας ή σε οποιαδήποτε άλλη καθορισμένη κατάσταση.

Προχωρήστε και ανοίξτε το app/page.js αρχείο, διαγράψτε τον κώδικα boilerplate Next.js και προσθέστε τον ακόλουθο κώδικα.

"use client" ;

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

Public Home Page</h1>

Ο παραπάνω κώδικας χρησιμοποιεί το useAuth γάντζο για τη διαχείριση της κατάστασης ελέγχου ταυτότητας. Με αυτόν τον τρόπο, αποδίδει υπό όρους μια δημόσια αρχική σελίδα με έναν σύνδεσμο προς το Σύνδεση διαδρομή σελίδας όταν ο χρήστης δεν έχει επαληθευτεί και εμφανίζει μια παράγραφο για έναν χρήστη με έλεγχο ταυτότητας.

Προσθέστε ένα ενδιάμεσο λογισμικό για την επιβολή εξουσιοδοτημένης πρόσβασης σε προστατευμένες διαδρομές

Στο src κατάλογο, δημιουργήστε ένα νέο middleware.js αρχείο και προσθέστε τον παρακάτω κώδικα.

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

Αυτός ο κώδικας ενδιάμεσου λογισμικού λειτουργεί ως φύλακας. Ελέγχει για να διασφαλίσει ότι όταν οι χρήστες θέλουν να αποκτήσουν πρόσβαση σε προστατευμένες σελίδες, είναι πιστοποιημένοι και εξουσιοδοτημένοι να έχουν πρόσβαση στις διαδρομές, επιπλέον της ανακατεύθυνσης μη εξουσιοδοτημένων χρηστών στη σελίδα σύνδεσης.

Ασφάλιση εφαρμογών Next.js

Ο έλεγχος ταυτότητας με διακριτικό είναι ένας αποτελεσματικός μηχανισμός ασφαλείας. Ωστόσο, δεν είναι η μόνη διαθέσιμη στρατηγική για την προστασία των εφαρμογών σας από μη εξουσιοδοτημένη πρόσβαση.

Για να ενισχυθούν οι εφαρμογές ενάντια στο δυναμικό τοπίο της κυβερνοασφάλειας, είναι σημαντικό να υιοθετήσετε μια ολοκληρωμένη ασφάλεια προσέγγιση που αντιμετωπίζει ολιστικά πιθανά κενά και τρωτά σημεία ασφάλειας για να εγγυηθεί διεξοδικά ΠΡΟΣΤΑΣΙΑ.