Nouveau : Datasets open source gratuits disponibles !Decouvrir →
💚
Intermediaire 25 min Vue

Securiser une application Vue

Pourquoi Securiser une application Vue ?

La sécurité est un aspect critique à considérer dans le développement d'applications Web, y compris celles basées sur Vue.js. Dans un monde où les cyberattaques sont de plus en plus sophistiquées et fréquentes, il est essentiel de protéger les données des utilisateurs et la confidentialité de l'application. Un cas concret d'importance serait une application de gestion financière où les informations personnelles et financières peuvent être sensibles.

Prerequis

  • Connaissances en JavaScript et ES6+
  • Familiarité avec Vue.js 2 ou 3
  • Compréhension des concepts fondamentaux de Vue (components, props, events)
  • Installation de Node.js et npm (https://nodejs.org/)
  • Un éditeur de code (VSCode recommandé)

Concepts fondamentaux

1. Authentification et Autorisation

L'authentification vérifie l'identité d'un utilisateur, tandis que l'autorisation détermine les actions qu'un utilisateur peut effectuer sur l'application.

Schéma mental :

Authentification -> Vérification de la validité des identifiants (user/password)
Autorisation    -> Attribution des droits d'accès basés sur les rôles

2. Cryptage des données sensibles

Les données sensibles doivent être cryptées avant leur stockage et/ou transmission pour prévenir toute usurpation.

Schéma mental :

Données sensibles -> Cryptage avant le stockage/transmission
Données chiffrées -> Décryptage pour l'utilisation

3. Utilisation de HTTPS

Le protocole HTTP sécurisé (HTTPS) assure la confidentialité et l'intégrité des communications entre le client et le serveur.

Schéma mental :

HTTP (non sécurisé) -> HTTPS (sécurisé)

Mise en pratique : projet fil rouge

Nous allons créer un simple gestionnaire de tâches qui permet aux utilisateurs de s'inscrire, de se connecter et d'ajouter/supprimer des tâches.

Structure du projet :

task-manager/
├── public/
│   ├── index.html
├── src/
│   ├── assets/
│   ├── components/
│       ├── TaskList.vue
│       ├── TaskForm.vue
│   ├── App.vue
│   ├── main.js
│   ├── store.js (Vuex)
│   ├── router.js (Vue Router)
├── package.json

Étape 1 : Initialisation du projet

npm init -y
npm install vue@next vue-router@next vuex@next axios

main.js :

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';

createApp(App)
  .use(router)
  .use(store)
  .mount('#app');

router.js :

import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Tasks from './views/Tasks.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/login', component: Login },
  { path: '/tasks', component: Tasks, meta: { requiresAuth: true } }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.state.isAuthenticated) {
      next({ path: '/login' });
    } else {
      next();
    }
  } else {
    next();
  }
});

export default router;

store.js :

import { createStore } from 'vuex';

export default createStore({
  state: {
    isAuthenticated: false,
    user: null
  },
  mutations: {
    SET_AUTH(state, status) {
      state.isAuthenticated = status;
    },
    SET_USER(state, user) {
      state.user = user;
    }
  },
  actions: {
    login({ commit }, user) {
      // Simulate API call
      setTimeout(() => {
        commit('SET_AUTH', true);
        commit('SET_USER', user);
        localStorage.setItem('user', JSON.stringify(user));
      }, 1000);
    },
    logout({ commit }) {
      commit('SET_AUTH', false);
      commit('SET_USER', null);
      localStorage.removeItem('user');
    }
  }
});

Étape 2 : Création des composants

TaskForm.vue :

<template>
  <form @submit.prevent="addTask">
    <input v-model="taskName" placeholder="Add new task" />
    <button type="submit">Submit</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      taskName: ''
    };
  },
  methods: {
    addTask() {
      // Simulate API call
      this.$store.dispatch('addTask', { name: this.taskName });
      this.taskName = '';
    }
  }
};
</script>

TaskList.vue :

<template>
  <ul>
    <li v-for="task in tasks" :key="task.id">
      task.name
      <button @click="deleteTask(task.id)">Delete</button>
    </li>
  </ul>
</template>

<script>
export default {
  computed: {
    tasks() {
      return this.$store.state.tasks;
    }
  },
  methods: {
    deleteTask(id) {
      // Simulate API call
      this.$store.dispatch('deleteTask', id);
    }
  }
};
</script>

App.vue :

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>

Étape 3 : Création des vues

Home.vue :

<template>
  <div>
    <h1>Welcome to Task Manager</h1>
    <router-link to="/tasks">Go to Tasks</router-link>
  </div>
</template>

<script>
export default {
  name: 'Home'
};
</script>

Login.vue :

<template>
  <form @submit.prevent="login">
    <input v-model="username" placeholder="Username" />
    <input type="password" v-model="password" placeholder="Password" />
    <button type="submit">Login</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    login() {
      const user = { username: this.username, password: this.password };
      this.$store.dispatch('login', user);
      this.$router.push('/tasks');
    }
  }
};
</script>

Tasks.vue :

<template>
  <div>
    <h1>Tasks</h1>
    <TaskForm />
    <TaskList />
  </div>
</template>

<script>
import TaskForm from './TaskForm.vue';
import TaskList from './TaskList.vue';

export default {
  name: 'Tasks',
  components: {
    TaskForm,
    TaskList
  }
};
</script>

Erreurs frequentes et debugging

1. Erreur : Cannot read property 'map' of undefined

Code incorrect :

computed: {
  tasks() {
    return this.$store.state.tasks.map(task => task.name);
  }
}

Code correct :

computed: {
  tasks() {
    return this.$store.state.tasks ? this.$store.state.tasks.map(task => task.name) : [];
  }
}

2. Erreur : Uncaught SyntaxError: Unexpected token 'import'

Code incorrect :

const axios = require('axios');

Code correct :

import axios from 'axios';

3. Erreur : Access Denied

Code incorrect :

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.state.isAuthenticated) {
      next({ path: '/login' });
    } else {
      next();
    }
  } else {
    next();
  }
});

Code correct :

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.state.isAuthenticated) {
      next({ path: '/login' });
    } else {
      next();
    }
  } else {
    next();
  }
});

Pour aller plus loin

1. Utilisation de OAuth pour une authentification plus sécurisée

  • Concept : OAuth est un protocole d'autorisation qui permet aux utilisateurs de partager des informations sans divulguer leurs identifiants.
  • Lien : https://oauth.net/2/

2. Cryptage des mots de passe avec Bcrypt

3. Utilisation de Webpack pour la gestion des assets

  • Concept : Webpack est un module bundler populaire qui permet de gérer les assets (CSS, images) dans un projet Vue.
  • Lien : https://webpack.js.org/

Défi pratique

Créez une application Vue simple qui utilise l'authentification JWT pour la sécurité des utilisateurs. L'application doit permettre aux utilisateurs de s'inscrire, de se connecter et d'accéder à une page sécurisée contenant une liste de tâches. Utilisez Vuex pour gérer l'état de l'application et Vue Router pour la navigation.

Besoin d'aide sur Vue ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelles sont les meilleures pratiques pour sécuriser une application Vue.js?
Pour sécuriser une application Vue.js, il est recommandé d'utiliser des bibliothèques comme Vuex pour la gestion de l'état et des routes sécurisées avec Vue Router. Il faut également utiliser des composants séparés pour les vues sensibles et appliquer des règles de validation côté serveur.
Comment gérer les sessions utilisateurs dans une application Vue.js?
Pour gérer les sessions utilisateurs, il est préférable d'utiliser le stockage local (localStorage) ou un serveur pour conserver l'état de la session. Les informations sensibles comme les tokens JWT devraient être stockées de manière sécurisée et ne devraient pas être exposées dans le code client.
Quelles mesures faut-il prendre pour prévenir les attaques XSS (Cross-Site Scripting) dans une application Vue.js?
Pour prévenir les attaques XSS, il est important de vérifier et de nettoyer toutes les entrées utilisateur avant de les afficher sur la page. Utiliser des directives v-html avec prudence et éviter l'utilisation directe de variables utilisateur à l'intérieur d'expressions HTML.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.