NgSysV.A Serious Svelte InfoSys: Eine Client-Server-Version
Dec 01, 2024 am 09:56 AMDiese Beitragsserie ist auf NgateSystems.com indiziert. Dort finden Sie auch eine äußerst nützliche Stichwortsuchfunktion.
Letzte Bewertung: 24. November
1. Einführung
Beitrag 3.3 brachte schlechte Nachrichten: Das Firestore-Authentifizierungsobjekt, das clientseitig zur Bereitstellung von Informationen über einen angemeldeten Benutzer verwendet wird, ist serverseitig nicht verfügbar. Dies hat folgende Konsequenzen:
Serverseitiger Datenbankcode muss die Firestore-API Admin verwenden. Dies liegt daran, dass der Firestore-Client-API-Code, der Aufrufe Datenbank-„Regeln“ unterliegt, die auf die Authentifizierung verweisen, fehlschlägt, wenn die Authentifizierung nicht verfügbar ist. Im Gegensatz dazu kümmern sich Admin-API-Aufrufe nicht um Datenbankregeln. Wenn Sie die Regeln fallen lassen würden, würden Client-API-Aufrufe serverseitig funktionieren, Ihre Datenbank wäre dadurch jedoch anfällig für Cyberangriffe (Sie arbeiten in Ihrer Live-Firestore-Datenbank, seit Sie Ihr lokales VSCode-Terminal verwenden – denken Sie darüber nach). .
Serverseitiger Code, der von Auth abgeleitete Datenelemente wie Benutzername und Benutzer-E-Mail verwendet, muss einen anderen Weg finden, diese Informationen abzurufen.
In diesem Beitrag wird beschrieben, wie Sie diese Probleme überwinden, um eine leistungsstarke Webanwendung zu erstellen, die serverseitig sicher und effizient läuft.
2. Authentifizierter serverseitiger Svelte-Code in der Praxis
Wenn Sie sich bereits an die Client-Anrufsignaturen gewöhnt haben, ist die Notwendigkeit, zur Firestore-Admin-API zu wechseln, ein Ärgernis. Daran wirst du dich aber schnell gewöhnen, sodass es dich nicht allzu sehr aufhalten sollte.
Benutzerdaten zu erhalten ist jedoch eine andere Sache. Bei vielen Anwendungen ist der Zugriff auf Benutzereigenschaften wie uId für deren Design von entscheidender Bedeutung. Beispielsweise muss eine Webanwendung möglicherweise sicherstellen, dass Benutzer nur ihre eigenen Daten sehen können. Leider ist es ziemlich schwierig, dies zu arrangieren. Los geht's:
- Zuerst müssen Sie auf dem Client eine Möglichkeit finden, ein „idToken“-Paket zu erstellen, das alles enthält, was Ihr serverseitiger Code möglicherweise über einen Benutzer wissen muss. Google bietet einen getIdToken()-Mechanismus, um dies aus den Authentifizierungssitzungsdaten des Benutzers zu erstellen.
- Dann müssen Sie eine Möglichkeit finden, dieses Paket an den Server weiterzuleiten. Der hier verwendete Mechanismus registriert dies in einem „Header“, der Client-Aufrufen an den Server hinzugefügt wird.
- Dann müssen Sie ein Google-„Dienstkonto“ erhalten, mit dem Sie Ihre Nutzung der Firestore Admin API auf einem Google-Server authentifizieren können. Die Schlüssel, die dies definieren, müssen sicher in Ihre Projektdateien eingebettet werden (erinnern Sie sich an die Diskussion zu firebaseConfig.env in Beitrag 3.3. ).
- Und schließlich muss Ihr serverseitiger Code diese Dienstkontoschlüssel überall dort bereitstellen, wo Sie eine Firestore-Datenbank verwenden müssen.
2.1 Einen idToken erhalten
Sehen Sie sich den folgenden Code aus dem <script> an. Abschnitt einer products-maintenance-sv/ page.svelte „Server“-Version des „regelfreundlichen“ products-maintenance-rf-Codes. Dabei wird getIdToken() verwendet, um auf die Firebase-Authentifizierungssitzung eines Benutzers zuzugreifen und ein idToken
zu erstellen
// src/routes/products-maintenance-sv/+page.svelte <script> import { auth } from "$lib/utilities/firebase-client"; import { onMount } from "svelte"; import { goto } from "$app/navigation"; onMount(async () => { if (!auth.currentUser) { // Redirect to login if not authenticated, with a redirect parameter goto("/login?redirect=/products-maintenance-sv"); return; } try { // Fetch the ID token directly const idToken = await auth.currentUser.getIdToken(); window.alert("idToken:" + JSON.stringify(idToken)); } catch (error) { window.alert("Error retrieving ID token:", error); } }); </script>
Sie haben die onMount()-Anordnung zuvor in products-maintenance-rf/page.svelte gesehen, wo sie verwendet wurde, um sicherzustellen, dass der Benutzer angemeldet ist. Sie wird jetzt auch verwendet, um eine idToken-Variable durch Aufrufen der asynchronen Authentifizierung abzurufen. currentUser.getIdToken().
Erstellen Sie einen neuen Ordner src/routes/products-maintenance-sv und fügen Sie den oben aufgeführten Code in eine neue page.svelte-Datei darin ein. Versuchen Sie nun, dies auf dem Entwicklungsserver unter http://localhost:5173/products-maintenance-sv auszuführen. Sobald Sie angemeldet sind (mit der zuletzt in [Beitrag 3.4] gesehenen Version von /login/ page.svelte(https://ngatelive.nw.r.appspot.com/redirect?post=3.4), sollte das idToken angezeigt werden in einer Warnmeldung.
Das Firebase-ID-Token ist ein JSON Web Token (JWT). Das JSON-Bit bedeutet, dass es sich um ein Objekt handelt, das mithilfe der „Javascript Object Notation“ als Zeichenfolge codiert ist (wenn dies Ihr erster Anblick eines „JSON“ ist, könnte es hilfreich sein, chatGPT nach Hintergrundinformationen zu fragen). JSONs werden häufig verwendet, wenn Sie Javascript-Objekte als Zeichenfolgen weitergeben müssen. Der JWT-JSON enthält alles, was Sie über einen Benutzer wissen müssen. Ich zeige Ihnen später in diesem Beitrag, wie Sie diese Informationen extrahieren – es ist nicht kompliziert.
2.2 Übergabe des idToken an den Server
Der in diesem Beitrag beschriebene Mechanismus sendet das „IdToken“ als „Cookie“ im „Request-Header“, der Serveranfragen begleitet. Ein „http-Header“ ist ein Informationspaket, das durch das Web geleitet wird, wenn eine clientbasierte page.svelte-Datei eine Anfrage an eine serverbasierte page.server.js-Datei sendet. Eine solche Anfrage wird jedes Mal gesendet, wenn Sie ein Firestore-Dokument lesen oder schreiben. Ein „Cookie“ ist eine Zeichenfolge, die jedem Anforderungsheader hinzugefügt wird.
Diese Regelung ist kompliziert, gilt aber als sicher. Aus Ihrer Sicht als IT-Student ist es auch deshalb interessant und lehrreich, weil es Einblicke in die Interna des Webdesigns gibt.
Ein clientseitiges Javascript-Programm könnte problemlos ein „normales“ Cookie setzen, das das JWT enthält, aber aus Sicherheitsgründen möchten Sie dies auf keinen Fall tun. Wenn Sie das können, dann kann es jeder. Eine serverseitige page.server.js-Datei hingegen kann mithilfe eines set-cookie-Aufrufs ein „http-only“-Cookie im Client-Browser setzen. Hier ist ein Beispiel:
// src/routes/products-maintenance-sv/+page.svelte <script> import { auth } from "$lib/utilities/firebase-client"; import { onMount } from "svelte"; import { goto } from "$app/navigation"; onMount(async () => { if (!auth.currentUser) { // Redirect to login if not authenticated, with a redirect parameter goto("/login?redirect=/products-maintenance-sv"); return; } try { // Fetch the ID token directly const idToken = await auth.currentUser.getIdToken(); window.alert("idToken:" + JSON.stringify(idToken)); } catch (error) { window.alert("Error retrieving ID token:", error); } }); </script>
Die Einstellung „httpOnly: true“ oben bedeutet, dass das Cookie zwar clientseitig gespeichert wird, aber nicht über Javascript darauf zugegriffen werden kann. So stellen Sie sicher, dass der hier eingestellte Wert vor Manipulationen geschützt ist.
Die Frage, die Sie sich jetzt stellen sollten, lautet: „Wie kann eine serverseitige page.server.js-Datei einen Set-Cookie-Befehl starten, um ein idToken festzulegen, wenn sie das idToken nicht kennt?“ .
Willkommen bei der Svelte server.js-Datei. Dabei handelt es sich um serverseitigen Code, der mit einem Javascript-Abrufbefehl vom clientseitigen Code aufgerufen werden kann. Ein solcher serverseitiger Code wird als „Endpunkt“ bezeichnet. Ein Abrufbefehl ist die native Methode von Javascript zum Senden einer Anfrage an einen webbasierten „Endpunkt“. Mit dem Befehl können Sie Daten in die Anfrage aufnehmen und auf diese Weise einen idToken-Wert auf den Server übertragen. Hier ist ein Beispiel:
// Set a secure, HTTP-only cookie with the `idToken` token const headers = { 'Set-Cookie': cookie.serialize('idToken', idToken, { httpOnly: true }) }; let response = new Response('Set cookie from server', { status: 200, headers, body: { message: 'Cookie set successfully' } // Optional message }); return response;
und so würde die server.js-Datei des Empfängers dies abrufen und ihr idToken extrahieren.
// client-side +page.svelte code const idToken = await user.getIdToken(); // Send token to the server to set the cookie fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ idToken }), });
Sie denken wahrscheinlich: „Warum verwendet dieser Code einen „Abruf“-Befehl, um etwas zu „senden“? aber da bist du ja. „Fetch“ wurde als vielseitige API zum Erstellen vieler verschiedener Arten von HTTP-Anfragen entwickelt. Bitten Sie chatGPT um ein Tutorial, wenn Sie Hintergrundinformationen erhalten möchten. Sehen Sie sich einige Beispiele an.
Der Vorschlag besteht nun darin, Ihre Anmeldeseite für den server.js-Aufruf verantwortlich zu machen, der das Nur-http-Cookie des Browsers setzt. Sobald das Cookie gesetzt ist, wird es automatisch zu jedem HTTP-Aufruf des Browsers hinzugefügt, bis es abläuft.
Um dies in Gang zu setzen, erstellen Sie neue Ordner und Dateien für die folgende login-and-set-cookie/page.svelte-Version der Anmeldeseite und den dazugehörigen api/set-cookie/server.js-Endpunkt:
// server-side +server.js code export async function POST({ request }) { const { idToken } = await request.json(); }
Beachten Sie, dass Sie zur Verwendung von api/set-cookie/server.js zunächst die npm-Bibliothek „cookie“ installieren müssen. Diese Bibliothek hilft bei der Erstellung ordnungsgemäß formatierter Cookies zur Aufnahme in HTTP-Antwortheader.
// src/routes/login-and-set-cookie/+page.svelte <script> import { onMount } from "svelte"; import { auth, app } from "$lib/utilities/firebase-client"; import { goto } from "$app/navigation"; // SvelteKit's navigation for redirection import { signInWithEmailAndPassword } from "firebase/auth"; let redirect; let email = ""; let password = ""; onMount(() => { // Parse the redirectTo parameter from the current URL const urlParams = new URLSearchParams(window.location.search); redirect = urlParams.get("redirect") || "/"; }); // this code will run after a successful login. auth.onAuthStateChanged(async (user) => { if (user) { const idToken = await user.getIdToken(); console.log("In login_awith-cookie : idToken: ", idToken); // Send token to the server to set the cookie fetch("/api/set-cookie", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ idToken }), }); window.alert("In with-cookie : cookie set"); goto(redirect); } }); async function loginWithMail() { try { const result = await signInWithEmailAndPassword( auth, email, password, ); } catch (error) { window.alert("login with Mail failed" + error); } } </script> <div> <pre class="brush:php;toolbar:false">// src/routes/api/set-cookie/+server.js import admin from 'firebase-admin'; import cookie from 'cookie'; export async function POST({ request }) { const { idToken } = await request.json(); try { // Verify the token with Firebase Admin SDK const decodedToken = await admin.auth().verifyIdToken(idToken); // Use the cookie.serialize method to create a 'Set-Cookie' header for inclusion in the POST // response. This will instruct the browser to create a cookie called 'idToken' with the value of idToken // that will be incorporated in all subsequent browser communication requests to pages on this domain. const headers = { 'Set-Cookie': cookie.serialize('idToken', idToken, { httpOnly: true, // Ensures the cookie is only accessible by the web server secure: true, // Ensures the cookie is only sent over HTTPS sameSite: 'None', // Allows the cookie to be sent in cross-site requests maxAge: 60 * 60, // 1 hour (same as Firebase ID token expiry) path: '/' // Ensures the cookie is sent with every request, regardless of the path. }) }; let response = new Response('Set cookie from login', { status: 200, headers, body: { message: 'Cookie set successfully' } // Optional message }); console.log("Cookie set") return response; } catch (err) { console.error("Error in login server function: ", err); let response = new Response('Set cookie from login', { status: 401, body: { message: 'Unauthorized' } // Optional message }); return response; } };
Es ist keine Abmeldeseite zum „Abmelden und Entfernen von Cookies“ erforderlich. Durch das Setzen eines neuen Cookies wird jede alte Version mit demselben Namen überschrieben.
2.3 Einrichten eines Dienstkontos in Ihrem Projekt
Ein Dienstkonto für ein Projekt ist ein Objekt voller sicherer Schlüssel und „Eigentümer“-Informationen (z. B. der Projekt-ID des Projekts). Wenn eine „page.server.js“-Datei ausgeführt wird, wird Google eine Kopie des darin eingebetteten Dienstkontos angezeigt. Wenn beide übereinstimmen, wird die Serverdatei authentifiziert.
Hier ist das Verfahren für:
- Erstellen und Herunterladen eines Dienstkontos für Ihr Projekt in der Cloud,
- Einbettung in Ihr Projekt und
- Installieren Sie in Ihrem Projekt die „firebase-admin“-Bibliothek, die für die Durchführung des Vergleichs erforderlich ist
2.3.1 Erstellen eines Dienstkontos
- Gehen Sie zur Google Cloud Console.
- Navigieren Sie zu IAM & Admin > Dienstkonten und überprüfen Sie, ob dies auf Ihr Svelte-Dev-Projekt verweist (über das Pulldown-Menü oben links). Der IAM-Bildschirm (Identity and Access Management) listet alle Cloud-Berechtigungen auf, die steuern, wer was mit den Google Cloud-Ressourcen für Ihr Projekt tun kann. Dies verdient einen eigenen „Beitrag“, aber jetzt ist nicht der richtige Zeitpunkt
- Wechseln Sie von der IAM-Seite zur Seite „Dienstkonten“, indem Sie mit der Maus über die Symbolleiste links auf dem Bildschirm fahren und auf die Schaltfläche mit der Bezeichnung „Dienstkonten“ klicken. Sie sollten sehen, dass bereits ein Standardkonto erstellt wurde.
- Klicken Sie oben auf der Seite auf die Schaltfläche „Dienstkonto erstellen“ und erstellen Sie ein neues Dienstkonto mit einem eindeutigen „Dienstkontonamen“ wie „svelte-dev“ (oder was auch immer Ihnen gefällt – er muss zwischen 6 und … liegen). 30 Zeichen lang und es können nur Kleinbuchstaben und Bindestriche angezeigt werden. Eine Version davon mit einem garantiert cloudweit eindeutigen Suffix wird in das Feld „Dienstkonto-ID“ übernommen.
Klicken Sie nun auf die Schaltfläche „Erstellen und fortfahren“ und fahren Sie mit dem Abschnitt „Diesem Dienstkonto Zugriff auf das Projekt gewähren“ fort. Öffnen Sie zunächst das Pulldown-Menü auf dem Feld. Das ist etwas kompliziert, da es zwei Panels hat. Im linken Bereich (mit Schieberegler) können Sie ein Produkt oder eine Dienstleistung auswählen. Auf der rechten Seite werden die Rollen aufgelistet, die für diesen Dienst verfügbar sind. Wählen Sie im linken Bereich den Dienst „Firebase“ und dann im rechten Bereich die Rolle „Admin SDK Administrator Service Agent“ aus. Klicken Sie auf „Weiter“ und dann auf „Fertig“, um zum Bildschirm „Dienstkonten“ zurückzukehren
Klicken Sie abschließend auf das „Drei-Punkte“-Menü rechts neben dem Eintrag für den Schlüssel „Firebase Admin SDK Service Agent“, den Sie gerade erstellt haben, und wählen Sie „Schlüssel verwalten“. Klicken Sie auf „Schlüssel hinzufügen“ > Neuen Schlüssel erstellen > JSON > Erstellen Sie und beachten Sie, dass in Ihrem Ordner „Downloads“ eine neue Datei angezeigt wird. Dies ist Ihr „Dienstkontoschlüssel“. Jetzt müssen Sie dies nur noch in Ihr Projekt einbetten.
- Erstellen Sie im Stammverzeichnis Ihres Projekts einen Ordner /secrets, um einen sicheren Speicherort für den Dienstkontoschlüssel bereitzustellen. Verschieben Sie die heruntergeladene Dienstkontodatei in eine Datei /secrets/serviceAccount.json und fügen Sie den Ordner „/secrets“ und den entsprechenden Bearbeitungsverlauf zu Ihrer Datei „.gitignore“ hinzu:
- Dienstkontoschlüssel, die es ermöglichen, Firestore Admin API-Befehle zu verwenden und somit die Datenbankregeln zu ignorieren
- Ein idToken-Cookie, das es ermöglicht, Details eines authentifizierten Benutzers abzurufen
2.3.2 Einbetten des heruntergeladenen Dienstkontos in Ihr Projekt
// src/routes/products-maintenance-sv/+page.svelte <script> import { auth } from "$lib/utilities/firebase-client"; import { onMount } from "svelte"; import { goto } from "$app/navigation"; onMount(async () => { if (!auth.currentUser) { // Redirect to login if not authenticated, with a redirect parameter goto("/login?redirect=/products-maintenance-sv"); return; } try { // Fetch the ID token directly const idToken = await auth.currentUser.getIdToken(); window.alert("idToken:" + JSON.stringify(idToken)); } catch (error) { window.alert("Error retrieving ID token:", error); } }); </script>
Dies ist ein weiteres Beispiel des zuvor in Beitrag 3.3 beschriebenen Schutzmechanismus, der Sie daran hindert, versehentlich Dateien in Git-Repositorys preiszugeben. Für Windows-Benutzer wäre es ein noch sichererer Ansatz, Windows-Umgebungsvariablen GOOGLE_APPLICATION_CREDENTIAL zu erstellen, um wichtige Referenzen bereitzustellen.
2.3.3 Installieren der Bibliothek „firebase-admin“ in Ihrem Projekt
Um den Vorgang „Serveranmeldung“ auszuführen, benötigt Ihr page.server.js-Code Zugriff auf die Firebase-Administrator-API. Sie erhalten dies, indem Sie „firebase-admin“ in Ihrem Projekt installieren:
// Set a secure, HTTP-only cookie with the `idToken` token const headers = { 'Set-Cookie': cookie.serialize('idToken', idToken, { httpOnly: true }) }; let response = new Response('Set cookie from server', { status: 200, headers, body: { message: 'Cookie set successfully' } // Optional message }); return response;
Sie können jetzt eine Admin-Referenz in Ihrem Code erstellen mit:
// client-side +page.svelte code const idToken = await user.getIdToken(); // Send token to the server to set the cookie fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ idToken }), });
Beachten Sie, dass sich die Syntax dieses Imports von der Syntax unterscheidet, die Sie bisher verwendet haben – es gibt keine geschweiften Klammern um das „admin“-Bit. Während Sie mit den anderen Bibliotheken, die Sie verwendet haben, benannte Komponenten importieren können, müssen Sie in dieser Version das Ganze aus einem Standard Admin-Export importieren. Dadurch werden die Komponenten als Eigenschaften wie admin.auth(), admin.firestore() usw. des übergeordneten Admin-Objekts bereitgestellt. Die Designer dieser Bibliothek sind der Ansicht, dass dies in dieser Situation eine praktischere Lösung ist.
Wenn Sie einen Standardimport verwenden, können Sie das importierte übergeordnete Objekt beliebig nennen (z. B. können Sie es myFirebaseAdmin anstelle von admin nennen). Vergleichen Sie diese Anordnung mit dem benannten Exportansatz der Datei lib/utilities/firebase-config, die Sie zuvor erstellt haben
2.4 Verwenden des Dienstkontos und des idToken in Ihrer page.server.js-Datei
Hier kommen Sie endlich zur Sache mit der Verwendung der Firestore-Administrator-API für den serverseitigen Zugriff auf eine Firestore-Datenbank.
Zuerst verwenden Sie Ihre Dienstkontoschlüssel, um Ihre App zu „initialisieren“ und erhalten so die Berechtigung, das adminDb-Objekt zu erstellen, das für die Verwendung der Admin-API erforderlich ist (so wie Sie db für die Client-API benötigen). Dann müssen Sie Ihr idToken aus dem Cookie abrufen und daraus alle Benutzerinhalte extrahieren, die Sie möglicherweise in Ihren Firestore-Aufrufen benötigen. An diesem Punkt können Sie diese Aufrufe endlich mit der Firestore Admin API codieren.
Kopieren Sie den unten aufgeführten Code in eine neue page.server.js-Datei in Ihrem Ordner src/routes/products-maintenance-sv. Dies ist eine „Serverversion“ des Produktwartungscodes, der erstmals in Beitrag 3.3 zu sehen war. Es wurde dort verwendet, um zu zeigen, wie serverseitiger Code, der versucht, die Firestore-Client-API zu verwenden, fehlschlägt, wenn die Sammlungen, die er adressiert, den Firestore-Datenbankregeln unterliegen. Diese neue Version profitiert von:
// src/routes/products-maintenance-sv/+page.svelte <script> import { auth } from "$lib/utilities/firebase-client"; import { onMount } from "svelte"; import { goto } from "$app/navigation"; onMount(async () => { if (!auth.currentUser) { // Redirect to login if not authenticated, with a redirect parameter goto("/login?redirect=/products-maintenance-sv"); return; } try { // Fetch the ID token directly const idToken = await auth.currentUser.getIdToken(); window.alert("idToken:" + JSON.stringify(idToken)); } catch (error) { window.alert("Error retrieving ID token:", error); } }); </script>
Beachten Sie die merkwürdige Art und Weise, wie der Code das Feld „userEmail“ erstellt
// Set a secure, HTTP-only cookie with the `idToken` token const headers = { 'Set-Cookie': cookie.serialize('idToken', idToken, { httpOnly: true }) }; let response = new Response('Set cookie from server', { status: 200, headers, body: { message: 'Cookie set successfully' } // Optional message }); return response;
Aufgrund des Methodennamens „VerifyIdToken“ fragen Sie sich möglicherweise, ob damit versucht wird, Ihren Benutzer erneut zu authentifizieren. Keine Sorge – das ist es nicht. Es führt lediglich eine Sicherheitsüberprüfung der eingebetteten „Signaturen“ des Tokens durch, um sicherzustellen, dass es nicht manipuliert wurde und nicht abgelaufen ist.
Das von verifyIdToken erstellte decodedToken ist ein einfaches Objekt, das E-Mail- und Benutzernameneigenschaften usw. für Ihren authentifizierten Benutzer enthält. Der nachfolgende Firestore-Code verwendet keines davon, aber Sie können sich sicher leicht vorstellen, wie dies geschehen könnte.
Ich schlage vor, dass Sie beim Codieren von Admin-API-Aufrufen erneut den „Boiler-Plate“-Ansatz verwenden – verwenden Sie bei Bedarf chatGPT, um den in Beitrag 10.1 dokumentierten Client-Code zu konvertieren.
Ersetzen Sie nun den Inhalt der Datei src/routes/products-maintenance-sv/ page.svelte, die Sie zuvor erstellt haben, durch den unten gezeigten Code. Dadurch wird ein Client-Frontend für die Datei „products-maintenance-sv/page.server.js“ bereitgestellt:
// src/routes/products-maintenance-sv/ page.svelte <script> import { onMount } from „svelte“; import { auth } from „$lib/utilities/firebase-client“; import { goto } from „$app/navigation“; import { productNumberIsNumeric } aus "$lib/utilities/productNumberIsNumeric"; // Überprüfen Sie die Authentifizierungsstatusänderung in einem onAuthStateChanged-Rückruf in onMount. Das scheint // bizarr, scheint aber die einzige Möglichkeit zu sein, serverseitige Aktivitäten abzuschließen und auth.currentUser in einen stabilen Zustand zu versetzen // Zustand. Dies war in der clientseitigen „reules-freundlichen“ Version kein Problem, wurde aber bald zu einem Problem // als page.server.js-Datei mit actions() hinzugefügt wurde. onMount(async () => { auth.onAuthStateChanged(async (user) => { if (!auth.currentUser) { // Zur Anmeldung weiterleiten, wenn nicht authentifiziert. Der Parameter teilt dem Login mit, wie es hierher zurückkommt goto("/login-and-set-cookie?redirect=/products-maintenance-sv"); } }); }); let productNumber; let productDetails; let productNumberClass = "productNumber"; let subscribeButtonClass = "submitButton"; Formular exportieren; </script> <form method="POST"> <Label> Produktnummer <Eingabe bind:value={productNumber} name="productNumber" > <p>Um dies auf Ihrem Entwicklungsserver auszuführen, melden Sie sich zunächst mit http://localhost:5173/logout ab. Führen Sie dann http://localhost:5173/products-maintenance-sv aus. Dadurch werden Sie aufgefordert, sich auf der Seite „Anmelden und Cookie setzen“ anzumelden. </p> <p>Sobald Sie sich erfolgreich angemeldet haben, wird Ihnen das bekannte Formular angezeigt, das Sie zum Erstellen eines neuen Produkts einlädt. </p> <p>Zu diesem Zeitpunkt sollte die Seite „Anmelden und Cookie setzen“ das idToken-Cookie sicher in Ihrem Browser gesetzt haben. Wenn Sie Daten eingeben und das Formular absenden, geht die Steuerung an den serverseitigen Code in products-maintenance-sv/page.server.js über. Dies authentifiziert sich selbst, indem es die in Ihr Projekt integrierten Servicecodes präsentiert und dann das idToken aus den Headern und seine Eingabedaten aus dem Formularobjekt in der Sveltekit-Anfrage abruft. Der Code hat mit den in idToken verfügbaren Benutzerdaten keine sinnvolle Wirkung, aber im VSCode-Terminal wird eine Protokollmeldung angezeigt, die den Wert von userEmail anzeigt. Schließlich fügt der Firestore-Administratorcode das neue Produkt der Produktdatenbanksammlung hinzu.</p> <p>Sie können bestätigen, dass das Update erfolgreich angewendet wurde, indem Sie die alte Seite http://localhost:5173/products-display-rf ausführen.</p> <p>Beachten Sie, dass nach dem Absenden des Formulars eine Bestätigungsmeldung angezeigt und die Eingabefelder gelöscht werden. „Formularaktualisierung“ ist die Standardaktion von Javascript nach der Formularübermittlung. </p><p>Sie fragen sich vielleicht, wie die Seite „http://localhost:5173/products-display-rf“ funktioniert, wenn noch Firestore <strong>Client</strong> API-Codeserverseite mit Firestore-Authentifizierungsregeln für die Produktsammlung ausgeführt wird. Der Unterschied besteht darin, dass diese Regeln nur auf Schreibvorgänge angewendet werden. Der products-display-rfcode liest lediglich Dokumente. </p> <p>In der Praxis denke ich, dass Sie, wenn Sie Verwirrung vermeiden möchten und sich dazu entschließen, eine „products-display-sv“-Version von „products-display-sv“ zu erstellen, durchgehend Firestore-<strong>Admin</strong>-API-Aufrufe verwenden sollten . Denken Sie jedoch daran, dass Sie dann zunächst Ihre Dienstkonto-Anmeldeinformationen bei initializeApp vorlegen müssen.</p> <h3> 3. Zusammenfassung </h3> <p>Das war ein langer Beitrag und wird Ihr Javascript bis an seine Grenzen beansprucht haben. Wenn du an dieser Stelle noch bei mir bist – gut gemacht. Wirklich, gut gemacht – Sie haben außergewöhnliche Beharrlichkeit bewiesen! </p> <p>Es macht Freude, mit den „clientseitigen“ Techniken zu arbeiten, die im vorherigen Beitrag vorgestellt wurden, aber ich hoffe, dass Sie die Sicherheits- und Geschwindigkeitsvorteile der serverseitigen Vereinbarungen zu schätzen wissen. Mit der Erfahrung wird die serverseitige Codeentwicklung genauso einfach und selbstverständlich wie die clientseitige Arbeit.</p> <p>Aber es gibt noch eine Sache zu tun. Obwohl Sie jetzt eine Webanwendung mit vielen Seiten entwickelt haben, die problemlos auf Ihrem Entwicklungsserver laufen, ist noch keine davon im Web sichtbar.</p> <p>Im nächsten Beitrag erfahren Sie, wie Sie Ihre Webanwendung auf einer Google AppEngine „bauen“ und bereitstellen und sie so der eifrigen Öffentlichkeit zugänglich machen. Das wird ein großer Moment! </p> <p>Ich hoffe, dass Sie noch die Energie haben, weiterzulesen und herauszufinden, was Sie tun müssen. Es ist nicht allzu schwierig.</p> <h3> Nachtrag: Wenn etwas schief geht – Kopfzeilen im Inspektor anzeigen </h3> <p>Tatsächlich geht die Zahl der Dinge, die in diesem Abschnitt für Sie schief gehen könnten, wahrscheinlich ins Unendliche. Versuchen Sie, nicht zu sehr in Panik zu geraten und behalten Sie die Ablagestruktur Ihres Projekts genau im Auge. Es ist allzu einfach, den richtigen Code in die falsche Datei oder die richtige Datei in den falschen Ordner zu bringen. Darüber hinaus kann es hilfreich sein, regelmäßig „den Boden freizumachen“, indem Sie Ihre Terminalsitzung beenden und neu starten. Zumindest haben Sie damit bei der Suche nach der ursprünglichen Ursache einer Fehlersequenz ein sauberes Blatt.</p> <p>Aber da Sie jetzt mit Headern und Cookies spielen, ist es auch nützlich zu wissen, dass das Inspektor-Tool des Browsers Ihnen visuelle Einblicke in diese Dinge geben kann. Der Inspektor kann Ihnen <strong>zeigen</strong>ein Cookie, das im Anforderungsheader einer Seite eingebettet ist.</p><p>Um diese Funktion in Aktion zu sehen, stellen Sie zunächst sicher, dass Sie mit https://myLiveUrl/logout vom Live-System abgemeldet sind (wobei myLiveUrl die Adresse Ihrer bereitgestellten Webanwendung ist). Führen Sie dann die Seite „products-maintenance=sv“ unter https://https://myLiveUrl/products-maintenance-sv aus. Melden Sie sich an, öffnen Sie den Inspektor im Formular „Neues Produkt eingeben“ und klicken Sie auf die Registerkarte „Netzwerk“. Dies zeigt nun die Liste der von einer Seite gestellten Netzwerkanfragen an.</p> <p>Fügen Sie nun über die Webapp ein neues Produkt ein und beobachten Sie, wie die Liste „Anfragen“ aktualisiert wird. Dies sind die Netzwerkanforderungen, die für die Durchführung dieses einfachen Updates erforderlich sind – eine überraschend lange Liste! Wenn Sie zurück zum Anfang dieser Liste scrollen, sollten Sie einen Eintrag für Ihre Seite „products-maintenance-sv“ finden. Wenn Sie darauf klicken, sollten im Bereich rechts neben der Anforderungsliste vollständige Details sowohl der Antwort als auch der Anforderungsheader für die Transaktion angezeigt werden. Der Screenshot unten zeigt das im Anforderungsheader eingebettete Cookie.</p> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173301818045981.jpg" class="lazy" alt="NgSysV.A Serious Svelte InfoSys: A Client-Server Version"></p>
Das obige ist der detaillierte Inhalt vonNgSysV.A Serious Svelte InfoSys: Eine Client-Server-Version. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heißer Artikel

Hot-Tools-Tags

Heißer Artikel

Heiße Artikel -Tags

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Ersetzen Sie Stringzeichen in JavaScript

JQuery überprüfen, ob das Datum gültig ist

HTTP-Debugging mit Knoten und HTTP-Konsole

Benutzerdefinierte Google -Search -API -Setup -Tutorial

JQuery fügen Sie Scrollbar zu Div hinzu
