Authentifizierung in Vue.js
Veröffentlicht: 2022-03-10Die Authentifizierung ist eine sehr notwendige Funktion für Anwendungen, die Benutzerdaten speichern. Es ist ein Prozess zur Überprüfung der Identität von Benutzern, um sicherzustellen, dass nicht autorisierte Benutzer nicht auf private Daten zugreifen können – Daten, die anderen Benutzern gehören. Dies führt zu eingeschränkten Routen, auf die nur authentifizierte Benutzer zugreifen können. Diese authentifizierten Benutzer werden verifiziert, indem ihre Anmeldedaten (dh Benutzername/E-Mail und Passwort) verwendet werden und ihnen ein Token zugewiesen wird, das verwendet wird, um auf die geschützten Ressourcen einer Anwendung zuzugreifen.
In diesem Artikel erfahren Sie Folgendes:
- Vuex-Konfiguration mit Axios
- Routen definieren
- Umgang mit Benutzern
- Umgang mit abgelaufenem Token
Abhängigkeiten
Wir werden mit den folgenden Abhängigkeiten arbeiten, die bei der Authentifizierung helfen:
- Axios
Zum Senden und Abrufen von Daten von unserer API - Vuex
Zum Speichern von Daten, die von unserer API stammen - Vue-Router
Zur Navigation und zum Schutz von Routen
Wir werden mit diesen Tools arbeiten und sehen, wie sie zusammenarbeiten können, um robuste Authentifizierungsfunktionen für unsere App bereitzustellen.
Die Backend-API
Wir werden eine einfache Blog-Site erstellen, die diese API nutzt. Sie können sich die Dokumente ansehen, um die Endpunkte zu sehen und zu sehen, wie Anfragen gesendet werden sollten.
In den Dokumenten werden Sie feststellen, dass nur wenige Endpunkte mit einer Sperre verbunden sind. Auf diese Weise wird gezeigt, dass nur autorisierte Benutzer Anforderungen an diese Endpunkte senden können. Die uneingeschränkten Endpunkte sind die Endpunkte /register
und /login
. Ein Fehler mit dem Statuscode 401
sollte zurückgegeben werden, wenn ein nicht authentifizierter Benutzer versucht, auf einen eingeschränkten Endpunkt zuzugreifen.
Nach erfolgreicher Anmeldung eines Benutzers wird der Zugriffstoken zusammen mit einigen Daten in der Vue-App empfangen, die zum Setzen des Cookies verwendet und an den Anforderungsheader angehängt werden, um für zukünftige Anforderungen verwendet zu werden. Das Back-End überprüft den Anforderungsheader jedes Mal, wenn eine Anforderung an einen eingeschränkten Endpunkt gesendet wird. Lassen Sie sich nicht dazu verleiten, das Zugriffstoken im lokalen Speicher zu speichern.
Gerüstprojekt
Führen Sie mit der Vue-CLI den folgenden Befehl aus, um die Anwendung zu generieren:
vue create auth-project
Navigieren Sie in Ihren neuen Ordner:
cd auth-project
Fügen Sie den vue-router hinzu und installieren Sie weitere Abhängigkeiten – vuex und axios:
vue add router npm install vuex axios
Führen Sie jetzt Ihr Projekt aus und Sie sollten sehen, was ich unten in Ihrem Browser habe:
npm run serve
1. Vuex-Konfiguration mit Axios
Axios ist eine JavaScript-Bibliothek, die verwendet wird, um Anfragen vom Browser an APIs zu senden. Laut der Vuex-Dokumentation;
„Vuex ist ein Zustandsverwaltungsmuster und eine Bibliothek für Vue.js-Anwendungen. Es dient als zentraler Speicher für alle Komponenten in einer Anwendung, wobei Regeln sicherstellen, dass der Status nur auf vorhersehbare Weise geändert werden kann.“
Was bedeutet das? Vuex ist ein Speicher, der in einer Vue-Anwendung verwendet wird, die es uns ermöglicht, Daten zu speichern , die für jede Komponente verfügbar sind, und Möglichkeiten bietet, diese Daten zu ändern. Wir verwenden Axios in Vuex, um unsere Anfragen zu senden und Änderungen an unserem Status (Daten) vorzunehmen. Axios wird in Vuex- actions
zum Senden von GET
und POST
verwendet, die erhaltene Antwort wird zum Senden von Informationen an die mutations
verwendet und aktualisiert unsere Geschäftsdaten.
Um das Zurücksetzen von Vuex nach dem Aktualisieren zu bewältigen, werden wir mit vuex-persistedstate
arbeiten, einer Bibliothek, die unsere Vuex-Daten zwischen dem Neuladen von Seiten speichert.
npm install --save vuex-persistedstate
Lassen Sie uns nun einen neuen store
in src
erstellen, um den Vuex-Speicher zu konfigurieren. Erstellen Sie im store
Ordner einen neuen Ordner; modules
und eine Datei index.js
. Es ist wichtig zu beachten, dass Sie dies nur tun müssen, wenn der Ordner nicht automatisch für Sie erstellt wird.
import Vuex from 'vuex'; import Vue from 'vue'; import createPersistedState from "vuex-persistedstate"; import auth from './modules/auth'; // Load Vuex Vue.use(Vuex); // Create store export default new Vuex.Store({ modules: { auth }, plugins: [createPersistedState()] });
Hier verwenden wir Vuex
und importieren ein module
aus dem modules
in unseren Shop.
Module
Module sind verschiedene Segmente unseres Shops, die ähnliche Aufgaben gemeinsam erledigen, darunter:
- Zustand
- Aktionen
- Mutationen
- Getter
Bevor wir fortfahren, bearbeiten wir unsere main.js
-Datei.
import Vue from 'vue' import App from './App.vue' import router from './router'; import store from './store'; import axios from 'axios'; axios.defaults.withCredentials = true axios.defaults.baseURL = 'https://gabbyblog.herokuapp.com/'; Vue.config.productionTip = false new Vue({ store, router, render: h => h(App) }).$mount('#app')
Wir haben das store
Objekt aus dem Ordner ./store
sowie das Axios-Paket importiert.
Wie bereits erwähnt, müssen das Zugriffstoken-Cookie und andere notwendige Daten, die von der API abgerufen werden, in den Anforderungsheadern für zukünftige Anforderungen festgelegt werden. Da wir beim Stellen von Anfragen Axios verwenden, müssen wir Axios konfigurieren, um dies zu verwenden. Im obigen Snippet verwenden wir dazu axios.defaults.withCredentials = true
, dies ist erforderlich, da standardmäßig keine Cookies von Axios weitergegeben werden.
aaxios.defaults.withCredentials = true
ist eine Anweisung an Axios, alle Anfragen mit Anmeldeinformationen zu senden, wie z. Autorisierungsheader, TLS-Client-Zertifikate oder Cookies (wie in unserem Fall).
Wir setzen unsere axios.defaults.baseURL
für unsere Axios-Anforderung an unsere API
. Auf diese Weise verwendet es immer dann, wenn wir über Axios senden, diese Basis-URL. Damit können wir unseren Aktionen nur unsere Endpunkte wie /register
und /login
hinzufügen, ohne jedes Mal die vollständige URL anzugeben.
Erstellen Sie nun im modules
im store
eine Datei namens auth.js
//store/modules/auth.js import axios from 'axios'; const state = { }; const getters = { }; const actions = { }; const mutations = { }; export default { state, getters, actions, mutations };
state
In unserem state
werden wir unsere Daten und ihre Standardwerte definieren:
const state = { user: null, posts: null, };
Wir legen den Standardwert von state
, bei dem es sich um ein Objekt handelt, das user
und posts
mit ihren Anfangswerten als null
enthält.
Aktionen
Aktionen sind Funktionen, die verwendet werden, um eine Mutation zu commit
, um den Zustand zu ändern, oder die verwendet werden können, um eine andere Aktion dispatch
, dh aufzurufen. Es kann in verschiedenen Komponenten oder Ansichten aufgerufen werden und begeht dann Mutationen unseres Zustands;
Aktion registrieren
Unsere Register
-Aktion nimmt Formulardaten entgegen, sendet die Daten an unseren /register
-Endpunkt und weist die Antwort einer Variablen response
zu. Als nächstes werden wir unseren Formularbenutzernamen und unser password
an unsere username
login
. Auf diese Weise melden wir den Benutzer an, nachdem er sich angemeldet hat, sodass er auf die Seite /posts
umgeleitet wird.
async Register({dispatch}, form) { await axios.post('register', form) let UserForm = new FormData() UserForm.append('username', form.username) UserForm.append('password', form.password) await dispatch('LogIn', UserForm) },
Login-Aktion
Hier findet die Hauptauthentifizierung statt. Wenn ein Benutzer seinen Benutzernamen und sein Passwort eingibt, wird es an einen User
übergeben, der ein FormData-Objekt ist, die LogIn
-Funktion nimmt das User
und sendet eine POST
-Anforderung an den /login
-Endpunkt, um den Benutzer anzumelden.
Die Login
-Funktion übergibt schließlich den username
an die setUser
Mutation.
async LogIn({commit}, User) { await axios.post('login', User) await commit('setUser', User.get('username')) },
Beitragsaktion erstellen
Unsere CreatePost
Aktion ist eine Funktion, die den post
aufnimmt und an unseren /post
-Endpunkt sendet und dann die GetPosts
Aktion absetzt. Dadurch kann der Benutzer seine Beiträge nach der Erstellung sehen.
async CreatePost({dispatch}, post) { await axios.post('post', post) await dispatch('GetPosts') },
Holen Sie sich die Posts-Aktion
Unsere GetPosts
Aktion sendet eine GET
-Anfrage an unseren /posts
-Endpunkt, um die Posts in unserer API abzurufen, und schreibt die setPosts
Mutation fest.
async GetPosts({ commit }){ let response = await axios.get('posts') commit('setPosts', response.data) },
Abmeldeaktion
async LogOut({commit}){ let user = null commit('logout', user) }
Unsere LogOut
Aktion entfernt unseren user
aus dem Browser-Cache. Es tut dies, indem es sich logout
:
Mutationen
const mutations = { setUser(state, username){ state.user = username }, setPosts(state, posts){ state.posts = posts }, LogOut(state){ state.user = null state.posts = null }, };
Jede Mutation übernimmt den state
und einen Wert von der Aktion, die sie festlegt, abgesehen von Logout
. Der erhaltene Wert wird verwendet, um bestimmte Teile oder alle zu ändern oder wie in LogOut
alle Variablen auf null zurückzusetzen.
Getter
Getter sind Funktionalitäten, um den Zustand zu erhalten. Es kann in mehreren Komponenten verwendet werden, um den aktuellen Status abzurufen. Die Funktion isAuthenticatated
prüft, ob state.user
definiert oder null ist und gibt jeweils true
oder false
zurück. StatePosts
und StateUser
geben den Wert state.posts
bzw. state.user
zurück.
const getters = { isAuthenticated: state => !!state.user, StatePosts: state => state.posts, StateUser: state => state.user, };
Jetzt sollte Ihre gesamte auth.js
-Datei meinem Code auf GitHub ähneln.
Komponenten einrichten
1. NavBar.vue
und App.vue
Komponenten
Löschen Sie in Ihrem Ordner src/components
HelloWorld.vue
und eine neue Datei namens NavBar.vue
.
Dies ist die Komponente für unsere Navigationsleiste, es wurden Links zu verschiedenen Seiten unserer Komponente hierher geleitet. Jeder Router-Link verweist auf eine Route/Seite in unserer App.
v-if="isLoggedIn"
ist eine Bedingung, um den Logout
anzuzeigen, wenn ein Benutzer angemeldet ist, und die Register
und Login
auszublenden. Wir haben eine logout
, auf die nur angemeldete Benutzer zugreifen können. Diese wird aufgerufen, wenn auf den Logout
geklickt wird. Es löst die LogOut
Aktion aus und leitet den Benutzer dann zur Anmeldeseite weiter.
<template> <div> <router-link to="/">Home</router-link> | <router-link to="/posts">Posts</router-link> | <span v-if="isLoggedIn"> <a @click="logout">Logout</a> </span> <span v-else> <router-link to="/register">Register</router-link> | <router-link to="/login">Login</router-link> </span> </div> </template> <script> export default { name: 'NavBar', computed : { isLoggedIn : function(){ return this.$store.getters.isAuthenticated} }, methods: { async logout (){ await this.$store.dispatch('LogOut') this.$router.push('/login') } }, } </script> <style> #nav { padding: 30px; } #nav a { font-weight: bold; color: #2c3e50; } a:hover { cursor: pointer; } #nav a.router-link-exact-active { color: #42b983; } </style>
Bearbeiten Sie nun Ihre App.vue
Komponente so, dass sie wie folgt aussieht:
<template> <div> <NavBar /> <router-view/> </div> </template> <script> // @ is an alias to /src import NavBar from '@/components/NavBar.vue' export default { components: { NavBar } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } </style>
Hier haben wir die NavBar-Komponente importiert, die wir oben erstellt haben, und im Vorlagenabschnitt vor dem <router-view />
platziert.
2. Ansichtskomponenten
Ansichtenkomponenten sind verschiedene Seiten in der App, die unter einer Route definiert werden und auf die über die Navigationsleiste zugegriffen werden kann. Gehen Sie zum Ordner views
, löschen Sie die Komponente About.vue
und fügen Sie die folgenden Komponenten hinzu:
-
Home.vue
-
Register.vue
-
Login.vue
-
Posts.vue
Home.vue
Home.vue
so um, dass es so aussieht:
<template> <div class="home"> <p>Heyyyyyy welcome to our blog, check out our posts</p> </div> </template> <script> export default { name: 'Home', components: { } } </script>
Dadurch wird den Benutzern beim Besuch der Homepage ein Begrüßungstext angezeigt.
Register.vue
Dies ist die Seite, auf der sich unsere Benutzer für unsere Anwendung anmelden können. Wenn die Benutzer das Formular ausfüllen, werden ihre Informationen an die API gesendet und zur Datenbank hinzugefügt und dann angemeldet.
Wenn Sie sich die API ansehen, erfordert der Endpunkt /register
einen username
, einen full_name
und ein password
unseres Benutzers. Lassen Sie uns nun eine Seite und ein Formular erstellen, um diese Informationen abzurufen:
<template> <div class="register"> <div> <form @submit.prevent="submit"> <div> <label for="username">Username:</label> <input type="text" name="username" v-model="form.username"> </div> <div> <label for="full_name">Full Name:</label> <input type="text" name="full_name" v-model="form.full_name"> </div> <div> <label for="password">Password:</label> <input type="password" name="password" v-model="form.password"> </div> <button type="submit"> Submit</button> </form> </div> <p v-if="showError">Username already exists</p> </div> </template>
In der Register
-Komponente müssen wir die Register
-Aktion aufrufen, die die Formulardaten empfängt.
<script> import { mapActions } from "vuex"; export default { name: "Register", components: {}, data() { return { form: { username: "", full_name: "", password: "", }, showError: false }; }, methods: { ...mapActions(["Register"]), async submit() { try { await this.Register(this.form); this.$router.push("/posts"); this.showError = false } catch (error) { this.showError = true } }, }, }; </script>
Wir beginnen mit dem Importieren von mapActions
aus Vuex. Dadurch werden Aktionen aus unserem Store in die Komponente importiert. Dadurch können wir die Aktion von der Komponente aufrufen.
data()
enthält den lokalen Zustandswert, der in dieser Komponente verwendet wird, wir haben ein form
, das username
, full_name
und password
enthält, wobei ihre Anfangswerte auf eine leere Zeichenfolge gesetzt sind. Wir haben auch showError
, das ist ein boolescher Wert, der verwendet wird, um entweder einen Fehler anzuzeigen oder nicht.
In den methods
importieren wir die Register
-Aktion mit den Mapactions
in die Komponente, damit die Register
-Aktion mit this.Register
aufgerufen werden kann.
Wir haben eine Submit-Methode, die die Register
-Aktion aufruft, auf die wir mit this.Register zugreifen können, indem wir this.Register
this.form
. Wenn kein error
auftritt, verwenden wir this.$router
, um den Benutzer zur Anmeldeseite zu schicken. Andernfalls setzen wir showError
auf true.
Danach können wir etwas Styling hinzufügen.
<style scoped> * { box-sizing: border-box; } label { padding: 12px 12px 12px 0; display: inline-block; } button[type=submit] { background-color: #4CAF50; color: white; padding: 12px 20px; cursor: pointer; border-radius:30px; } button[type=submit]:hover { background-color: #45a049; } input { margin: 5px; box-shadow:0 0 15px 4px rgba(0,0,0,0.06); padding:10px; border-radius:30px; } #error { color: red; } </style>
Login.vue
Auf unserer Anmeldeseite geben registrierte Benutzer ihren username
und ihr password
ein, um sich von der API zu authentifizieren und sich bei unserer Website anzumelden.
<template> <div class="login"> <div> <form @submit.prevent="submit"> <div> <label for="username">Username:</label> <input type="text" name="username" v-model="form.username" /> </div> <div> <label for="password">Password:</label> <input type="password" name="password" v-model="form.password" /> </div> <button type="submit">Submit</button> </form> <p v-if="showError">Username or Password is incorrect</p> </div> </div> </template>
Jetzt müssen wir unsere Formulardaten an die Aktion übergeben, die die Anfrage sendet, und sie dann auf die sichere Seite Posts
<script> import { mapActions } from "vuex"; export default { name: "Login", components: {}, data() { return { form: { username: "", password: "", }, showError: false }; }, methods: { ...mapActions(["LogIn"]), async submit() { const User = new FormData(); User.append("username", this.form.username); User.append("password", this.form.password); try { await this.LogIn(User); this.$router.push("/posts"); this.showError = false } catch (error) { this.showError = true } }, }, }; </script>
Wir importieren Mapactions
und verwenden sie beim Importieren der LogIn
-Aktion in die Komponente, die in unserer submit
-Funktion verwendet wird.
Nach der Login
wird der Benutzer auf die Seite /posts
umgeleitet. Im Fehlerfall wird der Fehler abgefangen und ShowError
auf true gesetzt.
Nun etwas Styling:
<style scoped> * { box-sizing: border-box; } label { padding: 12px 12px 12px 0; display: inline-block; } button[type=submit] { background-color: #4CAF50; color: white; padding: 12px 20px; cursor: pointer; border-radius:30px; } button[type=submit]:hover { background-color: #45a049; } input { margin: 5px; box-shadow:0 0 15px 4px rgba(0,0,0,0.06); padding:10px; border-radius:30px; } #error { color: red; } </style>
Posts.vue
Unsere Beitragsseite ist die gesicherte Seite, die nur authentifizierten Benutzern zur Verfügung steht. Auf dieser Seite erhalten sie Zugriff auf Beiträge in der API-Datenbank. Dies ermöglicht den Benutzern den Zugriff auf Beiträge und ermöglicht es ihnen auch, Beiträge für die API zu erstellen.
<template> <div class="posts"> <div v-if="User"> <p>Hi {{User}}</p> </div> <div> <form @submit.prevent="submit"> <div> <label for="title">Title:</label> <input type="text" name="title" v-model="form.title"> </div> <div> <textarea name="write_up" v-model="form.write_up" placeholder="Write up..."></textarea> </div> <button type="submit"> Submit</button> </form> </div> <div class="posts" v-if="Posts"> <ul> <li v-for="post in Posts" :key="post.id"> <div> <p>{{post.title}}</p> <p>{{post.write_up}}</p> <p>Written By: {{post.author.username}}</p> </div> </li> </ul> </div> <div v-else> Oh no!!! We have no posts </div> </div> </template>
Im obigen Code haben wir ein Formular, mit dem der Benutzer neue Beiträge erstellen kann. Das Absenden des Formulars sollte dazu führen, dass der Beitrag an die API gesendet wird – wir werden die Methode, die das tut, in Kürze hinzufügen. Wir haben auch einen Abschnitt, der Beiträge anzeigt, die von der API erhalten wurden (falls der Benutzer welche hat). Wenn der Benutzer keine Beiträge hat, zeigen wir einfach eine Nachricht an, dass es keine Beiträge gibt.
Die Getter StateUser
und StatePosts
werden gemappt, dh mit mapGetters
in Posts.vue
importiert und können dann im Template aufgerufen werden.
<script> import { mapGetters, mapActions } from "vuex"; export default { name: 'Posts', components: { }, data() { return { form: { title: '', write_up: '', } }; }, created: function () { // a function to call getposts action this.GetPosts() }, computed: { ...mapGetters({Posts: "StatePosts", User: "StateUser"}), }, methods: { ...mapActions(["CreatePost", "GetPosts"]), async submit() { try { await this.CreatePost(this.form); } catch (error) { throw "Sorry you can't make a post now!" } }, } }; </script>
Wir haben einen Anfangszustand für form
, das ein Objekt ist, das title
und write_up
als Schlüssel hat und dessen Werte auf eine leere Zeichenfolge gesetzt sind. Diese Werte ändern sich in das, was der Benutzer im Vorlagenbereich unserer Komponente in das Formular eingibt.
Wenn der Benutzer den Beitrag sendet, rufen wir this.CreatePost
, das das Formularobjekt empfängt.
Wie Sie im created
Lebenszyklus sehen können, haben wir this.GetPosts
, um Beiträge abzurufen, wenn die Komponente erstellt wird.
Etwas Styling,
<style scoped> * { box-sizing: border-box; } label { padding: 12px 12px 12px 0; display: inline-block; } button[type=submit] { background-color: #4CAF50; color: white; padding: 12px 20px; cursor: pointer; border-radius:30px; margin: 10px; } button[type=submit]:hover { background-color: #45a049; } input { width:60%; margin: 15px; border: 0; box-shadow:0 0 15px 4px rgba(0,0,0,0.06); padding:10px; border-radius:30px; } textarea { width:75%; resize: vertical; padding:15px; border-radius:15px; border:0; box-shadow:0 0 15px 4px rgba(0,0,0,0.06); height:150px; margin: 15px; } ul { list-style: none; } #post-div { border: 3px solid #000; width: 500px; margin: auto; margin-bottom: 5px;; } </style>
2. Routen definieren
Importieren Sie in unserer Datei router/index.js
unsere Ansichten und definieren Sie Routen für jede von ihnen
import Vue from 'vue' import VueRouter from 'vue-router' import store from '../store'; import Home from '../views/Home.vue' import Register from '../views/Register' import Login from '../views/Login' import Posts from '../views/Posts' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/register', name: "Register", component: Register, meta: { guest: true }, }, { path: '/login', name: "Login", component: Login, meta: { guest: true }, }, { path: '/posts', name: Posts, component: Posts, meta: {requiresAuth: true}, } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
3. Umgang mit Benutzern
- Unbefugte Benutzer
Wenn Sie beim Definieren unserer Postrouten bemerkt haben, dass wirmeta: {requiresAuth: true}
meta
hinzugefügt haben, um anzuzeigen, dass der Benutzer authentifiziert werden muss, brauchen wir jetzt einenrouter.BeforeEach
. Wenn eine Route denmeta
hat, überprüft sie den Store auf ein Token; Falls vorhanden, leitet es sie auf dielogin
um.
const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) router.beforeEach((to, from, next) => { if(to.matched.some(record => record.meta.requiresAuth)) { if (store.getters.isAuthenticated) { next() return } next('/login') } else { next() } }) export default router
- Autorisierte Benutzer
Wir haben auch einmeta
auf den Routen/register
und/login
. Dasmeta: {guest: true}
hindert angemeldete Benutzer daran, auf die Routen mit demguest
-Meta zuzugreifen.
router.beforeEach((to, from, next) => { if (to.matched.some((record) => record.meta.guest)) { if (store.getters.isAuthenticated) { next("/posts"); return; } next(); } else { next(); } });
Am Ende sollte Ihre Datei so aussehen:
import Vue from "vue"; import VueRouter from "vue-router"; import store from "../store"; import Home from "../views/Home.vue"; import Register from "../views/Register"; import Login from "../views/Login"; import Posts from "../views/Posts"; Vue.use(VueRouter); const routes = [ { path: "/", name: "Home", component: Home, }, { path: "/register", name: "Register", component: Register, meta: { guest: true }, }, { path: "/login", name: "Login", component: Login, meta: { guest: true }, }, { path: "/posts", name: "Posts", component: Posts, meta: { requiresAuth: true }, }, ]; const router = new VueRouter({ mode: "history", base: process.env.BASE_URL, routes, }); router.beforeEach((to, from, next) => { if (to.matched.some((record) => record.meta.requiresAuth)) { if (store.getters.isAuthenticated) { next(); return; } next("/login"); } else { next(); } }); router.beforeEach((to, from, next) => { if (to.matched.some((record) => record.meta.guest)) { if (store.getters.isAuthenticated) { next("/posts"); return; } next(); } else { next(); } }); export default router;
4. Umgang mit abgelaufenem Token (verbotene Anfragen)
Unsere API ist so eingestellt, dass Token nach 30 Minuten ablaufen. Wenn wir jetzt versuchen, nach 30 Minuten auf die posts
-Seite zuzugreifen, erhalten wir einen 401
-Fehler, was bedeutet, dass wir uns erneut anmelden müssen, also werden wir einen Interceptor setzen, der liest, wenn wir einen erhalten 401
-Fehler, dann werden wir zurück zur login
geleitet.
Fügen Sie das folgende Snippet nach der Axios-Standard-URL-Deklaration in der Datei main.js
.
axios.interceptors.response.use(undefined, function (error) { if (error) { const originalRequest = error.config; if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; store.dispatch('LogOut') return router.push('/login') } } })
Dies sollte Ihren Code in den gleichen Zustand bringen wie das Beispiel auf GitHub.
Fazit
Wenn Sie bis zum Ende mithalten konnten, sollten Sie jetzt in der Lage sein, eine voll funktionsfähige und sichere Front-End-Anwendung zu erstellen. Jetzt haben Sie mehr über Vuex und seine Integration mit Axios erfahren und auch, wie Sie seine Daten nach dem erneuten Laden speichern.
Der Code ist auf GitHub verfügbar →
Gehostete Website:
https://nifty-hopper-1e9895.netlify.app/
API:
https://gabbyblog.herokuapp.com
API-Dokumentation:
https://gabbyblog.herokuapp.com/docs
Ressourcen
- „Umgang mit Cookies mit Axios“, Aditya Srivastava, Medium
- „Erstellen eines Authentifizierungs-Navigationsschutzes in Vue“, Laurie Barth, Ten Mile Square Blog
- „Erste Schritte mit Vuex“, Offizieller Leitfaden
- „Vue.js JWT-Authentifizierung mit Vuex und Vue Router“, BezKoder