In meinen Anfängertagen beim Erstellen von Full-Stack-Webanwendungen mit ReactJs war ich verwirrt darüber, wie ich mit der Authentifizierung im Frontend umgehen sollte. Ich meine, was sollten Sie als Nächstes tun, nachdem Sie Ihr Zugriffstoken vom Backend erhalten haben? Wie bewahren Sie den Anmeldestatus auf?
Die meisten Anfänger würden annehmen: „Oh, speichern Sie Ihren Token einfach im Status.“ Aber ich habe schnell herausgefunden, dass es weder die beste Lösung noch überhaupt eine Lösung ist, denn wie die meisten erfahrenen ReactJs-Entwickler wissen, ist der Status temporär, da er jedes Mal gelöscht wird, wenn Sie die Seite aktualisieren, und wir können es auf jeden Fall tun. Es ist nicht möglich, dass sich der Benutzer bei jeder Aktualisierung anmeldet.
Jetzt, wo ich ein wenig Erfahrung beim Erstellen von Full-Stack-Apps in React gesammelt habe, den Authentifizierungsansatz eines erfahreneren Entwicklers studiert und den Prozess in zwei anderen Anwendungen repliziert habe, möchte ich einen Leitfaden geben darüber, wie ich derzeit damit umgehe. Manche Leute denken vielleicht nicht, dass es der beste Weg ist, aber ich habe es vorerst als meinen Weg übernommen und bin offen dafür, andere Methoden zu erlernen, die von anderen Entwicklern verwendet werden.
Sie haben Ihre E-Mail-Adresse und Ihr Passwort (vorausgesetzt, Sie verwenden die einfache E-Mail- und Passwort-Authentifizierung) an das Backend übermittelt, um den Authentifizierungsprozess zu starten. Ich werde nicht darüber sprechen, wie die Authentifizierung im Backend gehandhabt wird, da es in diesem Artikel ausschließlich darum geht, wie die Authentifizierung im Frontend gehandhabt wird. Ich gehe zu dem Teil über, in dem Sie in der HTTP-Antwort ein Token erhalten haben. Unten finden Sie ein Codebeispiel für eine einfache Anmeldeformularkomponente, die die E-Mail-Adresse und das Kennwort an den Server sendet und in der Antwort das Token und die Benutzerinformationen empfängt. Der Einfachheit halber werden meine Formularwerte jetzt mit dem Status verwaltet. Es wäre viel besser, eine robuste Bibliothek wie formik für Produktionsanwendungen zu verwenden.
import axios from 'axios' import { useState } from "react" export default function LoginForm() { const [email, setEmail] = useState("") const [password, setPassword] = useState("") const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo } catch (error) { throw error } } return() }
Verpacken Sie Ihre gesamte Anwendung oder nur die Teile, die Zugriff auf den Authentifizierungsstatus benötigen, in einen Authentifizierungskontextanbieter. Dies erfolgt üblicherweise in Ihrer Root-App.jsx-Datei. Wenn Sie keine Ahnung haben, was eine Kontext-API ist, schauen Sie sich gerne die Reactjs-Dokumente an. Die folgenden Beispiele zeigen die erstellte AuthContext-Anbieterkomponente. Anschließend wird es in App.jsx importiert und zum Umschließen des in der App-Komponente zurückgegebenen RouterProviders verwendet, wodurch der Authentifizierungsstatus von überall in der Anwendung zugänglich gemacht wird.
import { createContext } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { return({children} ) }
import React from "react"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import AuthProvider from "./AuthContext"; const router = createBrowserRouter([ // your routes here ]) function App() { return() } export default App
Im Authentifizierungskontext müssen Sie zwei Statusvariablen initialisieren, „isLoggedIn“ und „authenticatedUser“. Der erste Status ist ein boolescher Typ, der zunächst auf „false“ gesetzt und dann nach Bestätigung der Anmeldung auf „true“ aktualisiert wird. Die zweite Statusvariable wird zum Speichern der Informationen des angemeldeten Benutzers wie Namen, E-Mail-Adresse usw. verwendet. Diese Statusvariablen müssen in den Wert für den Anbieter einbezogen werden, der in der Kontextkomponente zurückgegeben wird, damit in der gesamten Anwendung für bedingtes Rendering auf sie zugegriffen werden kann .
import { createContext, useState } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
Nanostores ist ein Paket zur Statusverwaltung in Javascript-Apps. Das Paket bietet eine einfache API zum Verwalten von Zustandswerten über mehrere Komponenten hinweg, indem es einfach in einer separaten Datei initialisiert und in jede Komponente importiert wird, in der Sie den Zustand nutzen oder aktualisieren möchten. Zum Speichern Ihres Authentifizierungstokens, das Sie in Schritt 1 in der HTTP-Antwort erhalten haben, verwenden Sie jedoch nanostores/persistent. Dieses Paket behält Ihren Status bei, indem es ihn in localStorage speichert, sodass er nicht gelöscht wird, wenn Sie die Seite aktualisieren. @nanostores/react ist eine reaktionsspezifische Integration für Nanostores und stellt den useStore-Hook zum Extrahieren von Werten aus einem Nanostore-Status zur Verfügung.
Jetzt können Sie also fortfahren und:
Installieren Sie die folgenden Pakete: nanostores, @nanostores/persistent und @nanostores/react.
Initialisieren Sie in einer separaten Datei mit dem Namen user.atom.js oder einem beliebigen Namen einen „authToken“-Speicher und einen „user“-Speicher mit nanostores/persistent.
Importieren Sie sie in die Komponentendatei Ihres Anmeldeformulars und aktualisieren Sie den Status mit dem Token und den Benutzerdaten, die Sie in Ihrer Anmeldeantwort erhalten haben.
npm i nanostores @nanostores/persistent @nanostores/react
import { persistentMap } from '@nanostores/persistent' export const authToken = persistentMap('token', null) export const user = persistentMap('user', null)
import { authToken, user } from './user.atom' const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo authToken.set(token) user.set(userInfo) } catch (error) { throw error } }
Jetzt müssen Sie in Ihrem Authentifizierungskontext, der Ihre App umschließt, sicherstellen, dass die Token- und Benutzerzustände auf dem neuesten Stand gehalten und in Ihrer gesamten App verfügbar gemacht werden. Um dies zu erreichen, müssen Sie:
Importieren Sie die Stores „authToken“ und „user“.
Initiieren Sie einen useEffect-Hook. Erstellen Sie innerhalb des Hooks eine Funktion „checkLogin()“, die prüft, ob das Token im Speicher „authToken“ vorhanden ist. Wenn dies der Fall ist, führen Sie eine Funktion aus, um zu überprüfen, ob dies der Fall ist Abgelaufen. Basierend auf Ihren Prüfergebnissen leiten Sie den Benutzer entweder zur Anmeldeseite weiter, um sich authentifizieren zu lassen, ODER Sie setzen den Status „isLoggedIn“ auf „true“. Um nun sicherzustellen, dass der Anmeldestatus häufiger verfolgt wird, kann dieser Hook so eingestellt werden, dass er jedes Mal ausgeführt wird, wenn sich der aktuelle Pfad ändert. Auf diese Weise kann ein Benutzer rausgeschmissen oder zur Anmeldeseite weitergeleitet werden, wenn sein Token während der Interaktion mit der App abläuft .
Initialisieren Sie einen weiteren useEffect-Hook, der eine Funktion zum Abrufen der Benutzerinformationen vom Backend mithilfe des Tokens im authToken-Store jedes Mal enthält, wenn die App geladen oder aktualisiert wird. Wenn Sie eine erfolgreiche Antwort erhalten, setzen Sie den Status „isLoggedIn“ auf „true“ und aktualisieren Sie den Status „authenticatedUser“ und den Speicher „Benutzer“ mit den in der Antwort erhaltenen Benutzerinformationen.
Unten finden Sie die aktualisierte AuthProvider-Komponentendatei.
import { createContext, useState } from "react"; import { authToken, user } from './user.atom'; import { useStore } from "@nanostores/react"; import { useNavigate, useLocation } from "react-router-dom"; import axios from "axios"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const token = useStore(authToken) const navigate = useNavigate() const { pathname } = useLocation() function isTokenExpired() { // verify token expiration and return true or false } // Hook to check if user is logged in useEffect(() => { async function checkLogin () { if (token) { const expiredToken = isTokenExpired(token); if (expiredToken) { // clear out expired token and user from store and navigate to login page authToken.set(null) user.set(null) setIsLoggedIn(false); navigate("/login"); return; } } }; checkLogin() }, [pathname]) // Hook to fetch current user info and update state useEffect(() => { async function fetchUser() { const response = await axios.get("/api/auth/user", { headers: { 'Authorization': `Bearer ${token}` } }) if(response?.status !== 200) { throw new Error("Failed to fetch user data") } setAuthenticatedUser(response?.data) setIsLoggedIn(true) } fetchUser() }, []) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
Jetzt sind diese beiden useEffect-Hooks, die in Schritt fünf erstellt wurden, dafür verantwortlich, den Authentifizierungsstatus Ihrer gesamten App zu verwalten. Jedes Mal, wenn Sie eine Aktualisierung durchführen, überprüfen sie Ihr Token im lokalen Speicher, rufen die aktuellsten Benutzerdaten direkt vom Backend ab und aktualisieren Ihren „isLoggedIn“- und „authenticatedUser“-Status. Sie können die Zustände innerhalb jeder Komponente verwenden, indem Sie die Hooks „AuthContext“ und „useContext“ aus React importieren und sie innerhalb Ihrer Komponente aufrufen, um auf die Werte zuzugreifen und sie für ein bedingtes Rendering zu verwenden.
import { useContext } from "react"; import { AuthContext } from "./AuthContext"; export default function MyLoggedInComponent() { const { isLoggedIn, authenticatedUser } = useContext(AuthContext) return( { isLoggedIn ?Welcome {authenticatedUser?.name}
: } > ) }
Denken Sie daran, dass Sie beim Abmelden den Speicher „authToken“ und „user“ löschen müssen, indem Sie sie auf null setzen. Sie müssen außerdem „isLoggedIn“ auf „false“ und „authenticatedUser“ auf null setzen.
Danke fürs Lesen!
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3