Skip to content

16. Beispiel [nuxt-13]: Überprüfung der Navigation von [nuxt-12]

In diesem Beispiel befassen wir uns mit der Navigation von [nuxt-12]. Bei [nuxt-12] haben wir darauf verzichtet, da die Überprüfung der Navigation ein ohnehin schon komplexes Beispiel noch weiter verkompliziert hätte.

Ziel: Wir möchten, dass der Benutzer nur zulässige Aktionen ausführen kann:

  • Wenn die Sitzung jSON nicht gestartet wurde, ist nur die Sitzung URL [/] zulässig;
  • Wenn die Sitzung jSON gestartet wurde, der Benutzer jedoch nicht authentifiziert ist, ist nur die Sitzung URL [/authentification] zulässig;
  • Wenn die Sitzung jSON gestartet wurde und der Benutzer authentifiziert ist, sind nur die Sitzungen URL und [/get-admindata, /fin-session] zulässig;
  • wenn das aktuelle Routing-Ziel nicht autorisiert ist, erfolgt eine Umleitung zu einer autorisierten URL;

Das Beispiel [nuxt-13] wird zunächst durch Kopieren des Beispiels [nuxt-12] erstellt:

Image

Die Änderungen werden im Routing-Ordner von [middleware] vorgenommen.

16.1. Routing der Anwendung [nuxt]

Das Routing der Anwendung ist in der Datei [nuxt.config] wie folgt konfiguriert:


// Router
  router: {
    // Stamm der URL der Anwendung
    base: '/nuxt-13/',
    // Routing-Middleware
    middleware: ['routing']
},
  • Zeile 6: Das Routing der Anwendung wird durch die Datei [middleware/routing] gesteuert;

Die Datei [middleware/routing] lautet wie folgt:


/* eslint-disable no-console */

// Wir importieren die Server- und Client-Middleware
import serverRouting from './server/routing'
import clientRouting from './client/routing'

export default function(context) {
  // Wer führt diesen Code aus?
  console.log('[middleware], process.server', process.server, ', process.client=', process.client)
  if (process.server) {
    // Server-Routing
    serverRouting(context)
  } else {
    // Client-Routing
    clientRouting(context)
  }
}
  • Zeilen 10–16: Die Weiterleitungen des Clients und des Servers [nuxt] werden unterschiedlich behandelt. Dies ist ein Punkt, in dem sie sich erheblich unterscheiden;
  • Zeile 4: Die Server-Weiterleitung wird durch das Skript [middleware/server/routing] implementiert;
  • Zeile 5: Das Client-Routing wird durch das Skript [middleware/client/routing] implementiert;

16.2. Client-Routing [nuxt]

Das Client-Routing [nuxt] bleibt unverändert gegenüber [nuxt-12]:


/* eslint-disable no-console */
export default function(context) {
  // Wer führt diesen Code aus?
  console.log('[middleware client], process.server', process.server, ', process.client=', process.client)
  // Verwaltung des Sitzungs-Cookies PHP im Browser
  // Das Sitzungs-Cookie PHP des Browsers muss mit dem in der Nuxt-Sitzung gefundenen identisch sein
  // Die Aktion [fin-session] erhält ein neues Cookie PHP (sowohl vom Server als auch vom Nuxt-Client)
  // Wenn der Server es empfängt, muss der Client es an den Browser weiterleiten
  // für seine eigenen Datenaustausche mit dem Server PHP
  //– hier handelt es sich um ein Client-Routing

  // Das Sitzungs-Cookie PHP wird abgerufen
  const phpSessionCookie = context.store.state.phpSessionCookie
  if (phpSessionCookie) {
    // Falls vorhanden, wird das Sitzungs-Cookie PHP dem Browser zugewiesen
    document.cookie = phpSessionCookie
  }

  ...
}

Um zu verhindern, dass der Kunde auf nicht autorisierte Routen gelangt, bieten wir ihm im Kunden-Navigationsmenü lediglich die autorisierten Routen an. Die Komponente [components/navigation] sieht nun wie folgt aus:


<template>
  <!-- Bootstrap-Menü mit drei Optionen -->
  <b-nav vertical>
    <b-nav-item v-if="$store.state.jsonSessionStarted && !$store.state.userAuthenticated" to="/authentification" exact exact-active-class="active">
      Authentification
    </b-nav-item>
    <b-nav-item
      v-if="$store.state.jsonSessionStarted && $store.state.userAuthenticated && !$store.state.adminData"
      to="/get-admindata"
      exact
      exact-active-class="active"
    >
      Requête AdminData
    </b-nav-item>
    <b-nav-item v-if="$store.state.jsonSessionStarted && $store.state.userAuthenticated" to="/fin-session" exact exact-active-class="active">
      Fin session impôt
    </b-nav-item>
  </b-nav>
</template>
  • Zeile 4: Die Option [Authentification] wird nur angeboten, wenn die Sitzung jSON gestartet wurde, der Benutzer jedoch nicht authentifiziert ist. Wenn die Sitzung jSON nicht gestartet wurde oder der Benutzer bereits authentifiziert ist, wird die Option nicht angeboten;
  • Zeilen 7–11: Die Option [Requête AdminData] wird nur angeboten, wenn die Sitzung jSON gestartet wurde, der Benutzer authentifiziert ist und die Daten [AdminData] noch nicht abgerufen wurden. Ist eine dieser drei Bedingungen nicht erfüllt (Sitzung jSON nicht gestartet, Benutzer nicht authentifiziert oder die Daten [AdminData] bereits abgerufen), wird die Option nicht angeboten;
  • Zeile 15: Die Option [Fin session impôt] wird angeboten, sobald die Sitzung jSON gestartet und der Benutzer authentifiziert ist, andernfalls wird sie nicht angeboten;

16.3. Weiterleitung des Servers [nuxt]

Das Routing des Servers ist in der Regel komplexer als das des Clients, da der Benutzer beliebige URL-Adressen in die Adressleiste seines Browsers eingeben kann. Man kann dies zulassen (schließlich soll der Benutzer das eigentlich nicht tun) oder versuchen, die Dinge zu kontrollieren. Genau das werden wir hier im Beispiel tun, denn im Fall der Anwendung [nuxt-12] kann man durchaus darauf verzichten, da der Steuerberechnungsserver gut gegen solche manuell eingegebenen URL-Adressen geschützt ist und die entsprechenden Fehlermeldungen ausgeben kann. Das haben wir in [next-12] gesehen, wo es keinerlei Routing-Kontrolle gab.

Das Routing eines [nuxt]-Servers unterscheidet sich hinsichtlich des Konzepts der Weiterleitung erheblich von dem eines [nuxt]-Clients:

  • Wenn ein [nuxt]-Server umgeleitet wird, sendet er einen Umleitungsbefehl mit dem Ziel der Umleitung an den Client-Browser. Der Browser sendet daraufhin eine neue Anfrage an den [nuxt]-Server und fragt nach dem Ziel, das ihm übermittelt wurde. Es ist so, als hätte der Benutzer die Adresse URL des Umleitungsziels manuell eingegeben: Die gesamte Anwendung [nuxt] wird neu gestartet, und damit ihr gesamter Lebenszyklus (Server-Plugins, Store, Server-Routing, Seiten);
  • wird ein Client „[nuxt]“ umgeleitet, geschieht nichts dergleichen. Es findet lediglich ein Seitenwechsel statt, genau wie wenn der Benutzer auf einen Link geklickt hätte, der zum Ziel der Weiterleitung führt. Der Lebenszyklus ist dann ein anderer (Client-Routing, Anzeige des Ziels der Route);

Aus diesem Grund ist es ratsam, das Client-Routing vom Server-Routing zu trennen, auch wenn beide Codes ähnlich erscheinen mögen.

Das Server-Routing-Skript [middleware/server/routing] sieht wie folgt aus:


/* eslint-disable no-console */
export default function(context) {
  // Wer führt diesen Code aus?
  console.log('[middleware server], process.server', process.server, ', process.client=', process.client)

  // Wir rufen einige Informationen aus dem Speicher ab [nuxt]
  const store = context.store
  // Woher kommen wir?
  const from = store.state.from || 'nowhere'
  ...
}
  • Bei der Client-Routing-Funktion erhält die Routing-Funktion den Kontext [context] mit der Eigenschaft [context.from], die die Route der Seite angibt, von der man kommt. Die Route, zu der man wechselt, wird durch [context.route] ermittelt;
  • Bei der clientseitigen Weiterleitung erhält die Weiterleitungsfunktion den Kontext [context] ohne die Eigenschaft [context.from]. Die Server-Weiterleitung greift nur dann ein, wenn ein URL manuell beim Server [nuxt] angefordert wird. Es ist bekannt, dass in diesem Fall die gesamte Anwendung [nuxt] zurückgesetzt wird. Es ist, als würde man von vorne beginnen, und daher gibt es keinen Begriff der „vorherigen Seite“;
  • Dank der Sitzung [nuxt] wissen wir, dass der Server diese Sitzung wiederherstellen kann und somit nicht bei Null anfangen muss. In dieser Sitzung [nuxt] und insbesondere im Speicher dieser Sitzung speichern wir also den Namen der letzten Seite, die vom Client-Browser angezeigt wurde, bevor eine URL vom Server [nuxt] angefordert wurde;
  • Zeilen 7–9: Wir rufen den Namen der zuletzt vom Client-Browser angezeigten Seite ab. Beim Start der Anwendung ist diese Information [from] noch nicht im Speicher vorhanden. Daraufhin wird der Name [nowhere] der Variablen [from] zugewiesen;

Damit der Server [nuxt] den Namen der zuletzt vom Client-Browser angezeigten Seite aus dem Speicher abrufen kann, muss der Client [nuxt] diese Information ebenfalls in den Speicher schreiben. Das Routing-Skript des Clients [nuxt] wird daher wie folgt ergänzt:


/* eslint-disable no-console */
export default function(context) {
  // Wer führt diesen Code aus?
  console.log('[middleware client], process.server', process.server, ', process.client=', process.client)
  // Verwaltung des Sitzungs-Cookies PHP im Browser
  // Das Session-Cookie PHP des Browsers muss mit dem in der Nuxt-Session gefundenen identisch sein
  // Die Aktion [fin-session] erhält ein neues Cookie PHP (sowohl vom Server als auch vom Nuxt-Client)
  // Wenn der Server es empfängt, muss der Client es an den Browser weiterleiten
  // für seine eigenen Datenaustausche mit dem Server PHP
  // Hier handelt es sich um ein Client-Routing

  // Das Sitzungs-Cookie wird abgerufen: PHP
  const phpSessionCookie = context.store.state.phpSessionCookie
  if (phpSessionCookie) {
    // Falls vorhanden, wird das Sitzungs-Cookie PHP dem Browser zugewiesen
    document.cookie = phpSessionCookie
  }

  // Man speichert den Namen der Seite, zu der man wechselt, in der Sitzung – keine Server-Weiterleitung
  context.store.commit('replace', { serverRedirection: false, from: context.route.name })
  // Der Store wird in der Sitzung gespeichert: [nuxt]
  const session = context.app.$session()
  session.value.store = context.store.state
  session.save(context)
}
  • Die Zeilen 19–24 werden hinzugefügt;
  • Zeile 20: Der Name der Seite [context.route.name], die angezeigt werden soll und somit beim nächsten Routing die vorherige Seite darstellt, wird in den Speicher geschrieben. Außerdem werden wir sehen, dass der Server [nuxt] bei der Weiterleitung wissen muss, ob die aktuelle Weiterleitung aus einer vorherigen Weiterleitung des Servers [nuxt] stammt. Hier ist dies nicht der Fall, und daher setzen wir die Eigenschaft [serverRedirection] auf [false];
  • Zeilen 22–24: Der Status des Stores wird in der Sitzung [nuxt] gespeichert (Zeile 23), anschließend wird die Sitzung [nuxt] in einem Cookie gespeichert (Zeile 24), das wiederum im Browser des Kunden [nuxt] gespeichert wird;

Kehren wir zum Routing-Skript des Servers [nuxt] zurück:


/* eslint-disable no-console */
export default function(context) {
  // Wer führt diesen Code aus?
  console.log('[middleware server], process.server', process.server, ', process.client=', process.client)

  // Wir rufen einige Informationen aus dem Store ab [nuxt]
  const store = context.store
  // Woher kommen wir?
  const from = store.state.from || 'nowhere'
  // Wohin geht es?
  const to = context.route.name
  // Mögliche Weiterleitung
  let redirection = ''
  // Routing-Verarbeitung abgeschlossen
  let done = false

  // Befindet man sich bereits in einer Weiterleitung des Servers [nuxt]?
  if (store.state.serverRedirection) {
    // Keine Aktion erforderlich
    done = true
  }

  // Handelt es sich um einen Seitenneuladung?
  if (to === from) {
    // nichts zu tun
    done = true
  }
  
  // Überprüfung der Navigation des Servers [nuxt]
  // Orientierung an der Client-Navigation in der Komponente [navigation]

  // Fall, in dem die Sitzung PHP nicht gestartet wurde
  if (!done && !store.state.jsonSessionStarted && to !== 'index') {
    // Weiterleitung
    redirection = 'index'
    // Auftrag abgeschlossen
    done = true
  }

  // Fall, in dem der Benutzer nicht authentifiziert ist
  if (!done && store.state.jsonSessionStarted && !store.state.userAuthenticated && to !== 'authentification') {
    // Weiterleitung
    redirection = from
    // Auftrag abgeschlossen
    done = true
  }

  // Fall, in dem der Benutzer authentifiziert wurde
  if (!done && store.state.jsonSessionStarted && store.state.userAuthenticated && to !== 'get-admindata' && to !== 'fin-session') {
    // man bleibt auf derselben Seite
    redirection = from
    // Auftrag abgeschlossen
    done = true
  }

  // Fall, in dem [adminData] abgerufen wurde
  if (!done && store.state.jsonSessionStarted && store.state.userAuthenticated && store.state.adminData && to !== 'fin-session') {
    // man bleibt auf derselben Seite
    redirection = from
    // Arbeit abgeschlossen
    done = true
  }

  // Alle Prüfungen wurden durchgeführt ---------------------
  // Weiterleitung?
  if (redirection) {
    // Die Weiterleitung wird im Store vermerkt
    store.commit('replace', { serverRedirection: true })
  } else {
    // keine Weiterleitung
    store.commit('replace', { serverRedirection: false, from: to })
  }
  // Der Store wird in der Sitzung gespeichert [nuxt]
  const session = context.app.$session()
  session.value.store = store.state
  session.save(context)
  // Es erfolgt gegebenenfalls eine Weiterleitung
  if (redirection) {
    context.redirect({ name: redirection })
  }
}
  • Zeilen 6–9: Der Wert von [from] wird aus dem Speicher des Servers [nuxt] abgerufen;
  • Zeile 11: Das Ziel der aktuellen Weiterleitung wird notiert;
  • Zeile 13: Die Weiterleitung kann zu einer Umleitung des Client-Browsers führen. [redirection] ist das Ziel dieser Umleitung;
  • Zeile 15: [done] an [true] zeigt an, dass die Weiterleitung abgeschlossen ist;
  • Zeilen 17–21: Zunächst wird geprüft, ob die aktuelle Weiterleitung auf eine an den Client-Browser gesendete Umleitungsanfrage zurückgeht. Diese Information ist in der Eigenschaft [serverRedirection] des Stores gespeichert. Ist diese Eigenschaft auf „wahr“ gesetzt, bedeutet dies, dass der Server [nuxt] bei der vorherigen Anfrage an den Server [nuxt] eine Weiterleitung an den Client-Browser gesendet hat. In diesem Fall ist keine Weiterleitung erforderlich. Bei der vorherigen Anfrage hat der Router des Servers [nuxt] entschieden, dass der Client-Browser weitergeleitet werden soll. Diese Entscheidung muss nicht durch eine neue Weiterleitung in Frage gestellt werden;
  • Zeilen 23–27: Es wird geprüft, ob es sich bei der aktuellen Weiterleitung um ein Neuladen der Seite handelt. Wenn ja, wird der Vorgang zugelassen;
  • Ab Zeile 29 werden die Regeln übernommen, die in der Komponente [navigation] des Kunden [nuxt] angewendet werden (siehe vorheriger Absatz);
  • Zeilen 32–38: Hier wird der Fall behandelt, in dem die Sitzung jSON nicht gestartet wurde und das Ziel der Weiterleitung nicht die Seite [index] ist. In diesem Fall wird der Browser des Kunden auf die Seite [index] umgeleitet;
  • Zeilen 40–46: Hier wird der Fall behandelt, bei dem die Sitzung jSON gestartet wurde, der Benutzer nicht authentifiziert ist und das aktuelle Routing-Ziel nicht die Seite [authentification] ist. In diesem Fall wird das Routing abgelehnt und der aktuelle Zustand beibehalten;
  • Zeilen 48–54: Hier wird der Fall behandelt, bei dem die Sitzung jSON gestartet wurde, der Benutzer authentifiziert ist und das Ziel der aktuellen Weiterleitung weder die Seite [get-admindata] noch die Seite [fin-session] ist, die dann die einzigen möglichen Ziele sind. In diesem Fall wird die angeforderte Weiterleitung abgelehnt und man kehrt zum vorherigen Schritt zurück;
  • Zeilen 56–62: Hier wird der Fall behandelt, in dem [adminData] ermittelt wurde. In diesem Fall gibt es nur ein mögliches Ziel für die Weiterleitung: die Seite [fin-session]. Wenn diese nicht angefordert wurde, wird die Weiterleitung abgelehnt und man kehrt zum vorherigen Schritt zurück;
  • Zeilen 64–72: Wenn eine Weiterleitung stattgefunden hat, wird dies im Speicher des Servers [nuxt] vermerkt: [serverRedirection: true]. Es ist zu beachten, dass der Eigenschaft [from] im Speicher kein Wert zugewiesen wird. Der Grund dafür ist, dass eine Weiterleitung durch den Client-Browser erfolgt und wir gesehen haben, dass in diesem Fall kein Routing stattfindet (Zeilen 17–20) und die Eigenschaft [from] des Stores nicht verwendet wird;
  • Zeilen 66–69: Wenn keine Weiterleitung stattfindet, wird dies ebenfalls im Speicher des Servers vermerkt: [nuxt]: [serverRedirection: false]. Außerdem wird durch das aktuelle Routing die Seite [to] angezeigt, die für die nächste Anfrage (Client oder Server [nuxt]) zur vorherigen Seite wird. Deshalb wird [from: to] geschrieben;
  • Zeilen 73–76: Der Store wird in der Sitzung [nuxt] gespeichert, die wiederum in einem Cookie gespeichert ist;
  • Zeilen 77–80: Ist [redirection] nicht leer, wird der Browser angewiesen, eine Weiterleitung durchzuführen. Andernfalls (was hier nicht dargestellt ist) wird der Lebenszyklus des Servers [nuxt] fortgesetzt: Die Seite [to] wird vom Server [nuxt] verarbeitet und zusammen mit dem Sitzungs-Cookie [nuxt] an den Browser des Clients [nuxt] gesendet;

Die hier für den Server [nuxt] gewählte Weiterleitung ist willkürlich. Man hätte auch eine andere wählen oder, wie bereits erwähnt, ganz darauf verzichten können. Die oben gewählte Variante hat den Vorteil, dass die Anwendung unabhängig von der vom Benutzer angeforderten URL stets in einem stabilen Zustand bleibt.

Ein Punkt lässt sich verbessern, wenn die letztendlich geladene Seite die ursprüngliche Seite ist. Dabei gibt es zwei Fälle:

  • Der Benutzer hat ein Neuladen der Seite ausgelöst (to===from);
  • es gibt Weiterleitungen zur Originalseite (redirection===from);

In beiden Fällen wird die ursprüngliche Seite erneut ausgeführt, einschließlich ihres asynchronen Aufrufs an den Steuerberechnungsserver. Nehmen wir ein Beispiel: Wenn der Benutzer nach der Authentifizierung die Seite neu lädt (F5). In diesem Fall ergibt sich in der obigen Routing-Kette: [to]=[from]=[authentification]. Es findet keine Weiterleitung statt. Die Seite [to=authentification] wird vom Server [nuxt] ausgeführt. Wenn nichts unternommen wird, wird die Funktion [asyncData] erneut ausgeführt. Das ist unnötig, da die Authentifizierung bereits erfolgt ist.

Man kann dies verbessern, indem man die Seite [authentification] leicht abändert:


// asynchrone Daten
  async asyncData(context) {
    // Protokoll
    console.log('[authentification asyncData started]')
    // Es wird nichts doppelt ausgeführt, wenn die Seite bereits angefordert wurde
    if (process.server && context.store.state.userAuthenticated) {
      console.log('[authentification asyncData canceled]')
      return { result: '[succès]' }
    }
     // Client [nuxt]
    if (process.client) {
      // Wartezeit beginnt
      context.app.$eventBus().$emit('loading', true)
      // kein Fehler
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
      // Authentifizierung beim Server
...
  • Zeilen 6–9: Wenn die Seite vom Server [nuxt] ausgeführt wird und im Speicher festgestellt wird, dass die Authentifizierung bereits erfolgt ist, wird direkt das gewünschte Ergebnis zurückgegeben (Zeile 8);

Das Gleiche gilt für alle Seiten:

Seite [index]:


// asynchrone Daten
  async asyncData(context) {
    // Protokoll
    console.log('[index asyncData started]')
    // Wird nicht doppelt ausgeführt, wenn die Seite bereits angefordert wurde
    if (process.server && context.store.state.jsonSessionStarted) {
      console.log('[index asyncData canceled]')
      return { result: '[succès]' }
    }
    try {
...

Seite [get-admindata]


// asynchrone Daten
  async asyncData(context) {
    // Protokoll
    console.log('[get-admindata asyncData started]')
    // Es wird nichts doppelt ausgeführt, wenn die Seite bereits angefordert wurde
    if (process.server && context.store.state.adminData) {
      console.log('[get-admindata asyncData canceled]')
      return { result: context.store.state.adminData }
    }
    // Client
    if (process.client) {
      // Wartezeit beginnt
      context.app.$eventBus().$emit('loading', true)
      // kein Fehler
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
   ...  

Seite [fin-session]


// asynchrone Daten
  async asyncData(context) {
    // Protokoll
    console.log('[fin-session asyncData started]')
    // Man macht nichts zweimal, wenn die Seite bereits angefordert wurde
    if (process.server && context.store.state.jsonSessionStarted && !context.store.state.userAuthenticated) {
      console.log('[fin-session asyncData canceled]')
      return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
    }
    // Fall des Kunden [nuxt]
    if (process.client) {
      // Wartezeit beginnt
      context.app.$eventBus().$emit('loading', true)
      // kein Fehler
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
   

16.4. Exécution

Um dieses Beispiel auszuführen, müssen Sie vor der Ausführung darauf achten, das Sitzungs-Cookie [nuxt] und das Cookie PHP aus dem Browser zu löschen, in dem der Client [nuxt] ausgeführt wird, um von einer sauberen Ausgangssituation auszugehen. Nachfolgend ein Beispiel mit dem Chrome-Browser:

Image

16.5. Conclusion

Das Routing des Servers [nuxt] ist komplex, da alle URL berücksichtigt werden müssen, die der Benutzer manuell eingeben könnte. Dies ist ein typisches Beispiel. Eine Anwendung [nuxt] ist nicht für eine solche Nutzung vorgesehen. Sobald die Seite [index] vom Router des Servers [nuxt] bereitgestellt wurde, könnten nachfolgende Aufrufe an den Server auf eine Fehlerseite umgeleitet werden.

Im konkreten Fall unseres Beispiels [nuxt-13] war die Weiterleitung durch den Server [nuxt] unnötig. Die standardmäßige Vorgehensweise (also das Fehlen einer Weiterleitung) im Beispiel [nuxt-12] war völlig ausreichend.