slogan3

Help me een Vue.js single-page applicatie (SPA) te maken met authenticatie en rolgebaseerde toegangscontrole.

description

Door deze gids te volgen, leer je hoe je veilige gebruikersauthenticatie implementeert en verschillende toegangs niveaus binnen je applicatie beheert, waardoor de beveiliging en gebruikerservaring worden verbeterd.

prompt

try_prompt

Help me bij het bouwen van een Vue.js single-page applicatie (SPA) die gebruikersauthenticatie en rolgebaseerde toegangscontrole bevat. Leg uit hoe je de authenticatiestroom opzet, geb ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder vind je een stapsgewijze uitleg om een Vue.js SPA te bouwen met JWT-gebaseerde authenticatie, gebruikersrollen en routebeveiliging: 1. Authenticatiestroom opzetten a. Login API integratie: - Maak een login-component waar gebruikers hun inloggegevens invoeren. - Bij login stuur je een POST-verzoek naar je backend API (bijvoorbeeld /api/auth/login) met gebruikersnaam en wachtwoord. - Bij succesvolle authenticatie ontvang je een JWT-token en mogelijk gebruikersgegevens met rolinformatie. b. Token opslaan: - Bewaar het JWT-token in de browser, bijvoorbeeld in localStorage of Vuex store. - Bijvoorbeeld: ```js localStorage.setItem('token', response.data.token); ``` c. Token gebruiken: - Voeg het token toe aan elke API-aanroep via een Authorization-header: ```js axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; ``` 2. Gebruikersrollen beheren a. Rollen ophalen: - Na inloggen, decodeer het JWT-token (bijvoorbeeld met jwt-decode) om de rol direct te kunnen gebruiken. - Of, als de backend de rol retourneert, sla deze op samen met de gebruiker. b. Rolcontrole: - Bewaar de rol in Vuex store of een globale state voor eenvoudige toegang. 3. Routes beveiligen op basis van gebruikersmachtigingen a. Vue Router setup: - Definieer routes en voeg meta-data toe voor toegang: ```js const routes = [ { path: '/admin', component: AdminComponent, meta: { requiresAuth: true, roles: ['admin'] } }, // andere routes ]; ``` b. Route guards instellen: - Gebruik een globale beforeEach guard om authenticatie en autorisatie te controleren: ```js router.beforeEach((to, from, next) => { const token = localStorage.getItem('token'); const userRole = /* haal rol uit Vuex of decodeer token */; if (to.matched.some(record => record.meta.requiresAuth)) { if (!token) { // Niet ingelogd, redirect naar login next({ path: '/login' }); } else { // Controleer rol const roles = to.meta.roles; if (roles && roles.includes(userRole)) { next(); } else { // Toegang geweigerd next({ path: '/unauthorized' }); } } } else { next(); } }); ``` 4. Overige tips - Zorg dat je backend JWT-verificatie correct is ingesteld en dat de rollen veilig worden meegegeven. - Gebruik HTTPS om tokens veilig te verzenden. - Voeg een logout-functie toe die het token verwijdert en de gebruiker uitlogt. Door deze stappen te volgen, bouw je een Vue.js SPA met JWT-authenticatie, rolgebaseerde toegangscontrole en routebeveiliging voor bijvoorbeeld de /admin pagina.
provider: deepseek
model: deepseek-chat
Hier is een stapsgewijze uitleg voor het bouwen van een Vue.js SPA met JWT-authenticatie en rolgebaseerde toegangscontrole: ## 1. Projectopzet en Dependencies ```bash npm install vue-router vuex axios ``` ## 2. Authenticatiestroom met JWT ### Auth Store (Vuex) ```javascript // store/auth.js import axios from 'axios'; const state = { token: localStorage.getItem('token') || '', user: JSON.parse(localStorage.getItem('user')) || null, isAuthenticated: !!localStorage.getItem('token') }; const mutations = { SET_TOKEN(state, token) { state.token = token; localStorage.setItem('token', token); }, SET_USER(state, user) { state.user = user; localStorage.setItem('user', JSON.stringify(user)); }, SET_AUTHENTICATED(state, status) { state.isAuthenticated = status; }, CLEAR_AUTH(state) { state.token = ''; state.user = null; state.isAuthenticated = false; localStorage.removeItem('token'); localStorage.removeItem('user'); } }; const actions = { async login({ commit }, credentials) { try { const response = await axios.post('/api/auth/login', credentials); const { token, user } = response.data; commit('SET_TOKEN', token); commit('SET_USER', user); commit('SET_AUTHENTICATED', true); // Stel Authorization header in voor toekomstige requests axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; return response.data; } catch (error) { commit('CLEAR_AUTH'); throw error; } }, logout({ commit }) { commit('CLEAR_AUTH'); delete axios.defaults.headers.common['Authorization']; }, initializeAuth({ commit }) { const token = localStorage.getItem('token'); if (token) { commit('SET_TOKEN', token); commit('SET_AUTHENTICATED', true); axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; } } }; const getters = { isAdmin: state => state.user?.role === 'admin', isAuthenticated: state => state.isAuthenticated, currentUser: state => state.user }; export default { namespaced: true, state, mutations, actions, getters }; ``` ## 3. Router Configuratie met Route Guards ```javascript // router/index.js import { createRouter, createWebHistory } from 'vue-router'; import store from '../store'; const routes = [ { path: '/', name: 'Home', component: () => import('../views/Home.vue'), meta: { requiresAuth: false } }, { path: '/login', name: 'Login', component: () => import('../views/Login.vue'), meta: { requiresAuth: false } }, { path: '/admin', name: 'Admin', component: () => import('../views/Admin.vue'), meta: { requiresAuth: true, requiresAdmin: true } }, { path: '/profile', name: 'Profile', component: () => import('../views/Profile.vue'), meta: { requiresAuth: true } } ]; const router = createRouter({ history: createWebHistory(), routes }); // Globale route guard router.beforeEach((to, from, next) => { const requiresAuth = to.matched.some(record => record.meta.requiresAuth); const requiresAdmin = to.matched.some(record => record.meta.requiresAdmin); const isAuthenticated = store.getters['auth/isAuthenticated']; const isAdmin = store.getters['auth/isAdmin']; if (requiresAuth && !isAuthenticated) { // Redirect naar login als authenticatie vereist is next('/login'); } else if (requiresAdmin && !isAdmin) { // Redirect naar home als admin rechten vereist zijn next('/'); } else { next(); } }); export default router; ``` ## 4. Login Component ```vue <!-- views/Login.vue --> <template> <div class="login-container"> <form @submit.prevent="handleLogin"> <div> <label>Email:</label> <input v-model="credentials.email" type="email" required> </div> <div> <label>Wachtwoord:</label> <input v-model="credentials.password" type="password" required> </div> <button type="submit" :disabled="loading"> {{ loading ? 'Inloggen...' : 'Inloggen' }} </button> <div v-if="error" class="error">{{ error }}</div> </form> </div> </template> <script> import { mapActions } from 'vuex'; export default { name: 'Login', data() { return { credentials: { email: '', password: '' }, loading: false, error: '' }; }, methods: { ...mapActions('auth', ['login']), async handleLogin() { this.loading = true; this.error = ''; try { await this.login(this.credentials); this.$router.push('/'); } catch (error) { this.error = 'Inloggen mislukt. Controleer je gegevens.'; } finally { this.loading = false; } } } }; </script> ``` ## 5. Admin Component met Beveiliging ```vue <!-- views/Admin.vue --> <template> <div class="admin-dashboard"> <h1>Admin Dashboard</h1> <p>Welkom, {{ currentUser.name }} ({{ currentUser.role }})</p> <!-- Alleen zichtbaar voor admins --> <div v-if="isAdmin"> <h2>Beheer Gebruikers</h2> <button @click="fetchUsers">Gebruikers Ophalen</button> <ul> <li v-for="user in users" :key="user.id"> {{ user.name }} - {{ user.role }} </li> </ul> </div> </div> </template> <script> import { mapGetters } from 'vuex'; import axios from 'axios'; export default { name: 'Admin', data() { return { users: [] }; }, computed: { ...mapGetters('auth', ['isAdmin', 'currentUser']) }, methods: { async fetchUsers() { try { const response = await axios.get('/api/admin/users'); this.users = response.data; } catch (error) { console.error('Fout bij ophalen gebruikers:', error); } } } }; </script> ``` ## 6. Hoofd App Component ```vue <!-- App.vue --> <template> <div id="app"> <nav> <router-link to="/">Home</router-link> <router-link v-if="!isAuthenticated" to="/login">Login</router-link> <router-link v-if="isAuthenticated" to="/profile">Profiel</router-link> <router-link v-if="isAdmin" to="/admin">Admin</router-link> <button v-if="isAuthenticated" @click="logout">Uitloggen</button> </nav> <router-view /> </div> </template> <script> import { mapGetters, mapActions } from 'vuex'; export default { name: 'App', computed: { ...mapGetters('auth', ['isAuthenticated', 'isAdmin']) }, methods: { ...mapActions('auth', ['logout', 'initializeAuth']) }, created() { this.initializeAuth(); } }; </script> ``` ## 7. Store Configuratie ```javascript // store/index.js import { createStore } from 'vuex'; import auth from './auth'; export default createStore({ modules: { auth } }); ``` ## 8. Main.js Configuratie ```javascript // main.js import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; import store from './store'; const app = createApp(App); app.use(store); app.use(router); app.mount('#app'); ``` ## Belangrijke Beveiligingsoverwegingen: 1. **JWT Opslag**: Gebruik `localStorage` (zoals hier) of overweeg `httpOnly` cookies voor betere beveiliging 2. **Token Verlenging**: Implementeer token refresh mechanisme 3. **Axios Interceptor**: Voeg response interceptor toe voor 401 errors 4. **Route Guards**: Altijd server-side validatie toevoegen naast client-side 5. **XSS Bescherming**: Sanitize user input om XSS aanvallen te voorkomen Deze implementatie biedt een solide basis voor JWT-authenticatie met rolgebaseerde toegangscontrole in Vue.js!