Fermer

mai 7, 2019

Options de stockage dans le navigateur (partie 1)


Devez-vous utiliser le stockage local ou des cookies pour stocker votre jeton d'authentification? Quels sont les compromis pour chaque approche et comment pouvez-vous les lier ensemble? Saviez-vous que localStorage peut même être utilisé pour synchroniser la déconnexion sur plusieurs onglets?

Stockage dans le navigateur

Dans les applications React, nous stockons généralement nos données dans un état, à l'aide de l'état du composant ou d'un outil de gestion de l'état tel que Redux et MobX. . Cela fonctionne très bien jusqu'à ce que l'utilisateur actualise la page. Nous devons ensuite repartir de zéro et extraire à nouveau toutes les données de notre serveur afin de peupler à nouveau l'état.

Il existe de nombreuses situations dans lesquelles nous pourrions vouloir conserver les données de manière à ce que l'utilisateur actualise la page. , tout n'est pas perdu. Imaginez un monde où l'utilisateur devait s'authentifier chaque fois qu'il rafraichissait la page!

Dans cette série en deux parties, nous allons examiner quatre façons différentes de stocker des données dans le navigateur : stockage local sessionStorage cookies et indexés BD (19459009). Pourquoi tant de façons? Ils sont chacun utiles dans différentes circonstances et ont des capacités différentes. Dans cet article, nous verrons comment en tirer le meilleur parti dans une application de prise de notes comprenant une authentification JWT (avec déconnexion synchronisée) ainsi que des notes «brouillon» pouvant être synchronisées ultérieurement sur le serveur.

Le code source de ce projet se trouve à l'adresse suivante: https://github.com/leighhalliday/leigh-notes-web . La version finale de cette application se trouve à https://leigh-notes-web.herokuapp.com/ .

Présentation du stockage côté client

  • localStorage : Une clé / valeur magasin qui vit entièrement dans le client (navigateur). Utile pour stocker des jetons d'authentification qui n'ont pas besoin d'être envoyés au serveur – lorsqu'aucun rendu côté serveur (SSR) n'est utilisé.
  • sessionStorage : Magasin de clé / valeur qui fonctionne de manière similaire à localStorage, mais qui a expiré. / effacé lorsque l'utilisateur ferme la page et qu'il n'est pas partagé entre les onglets, même sur le même domaine. Très utile pour stocker des données temporaires.
  • Cookies : données qui peuvent être lues et écrites dans le navigateur, mais sont également acheminées vers le serveur avec chaque demande dans l'en-tête du cookie.
  • IndexDB : Comme son nom l'indique, une base de données qui réside dans le navigateur. Un peu difficile à utiliser seul, mais associé à un outil tel que PouchDB, peut être utile pour stocker des données côté client plus complexes, qui doivent être interrogées et performantes.

localStorage and sessionStorage

LocalStorage et sessionStorage sont des magasins de clés / valeurs qui utilisent l'objet Storage . La clé et la valeur doivent être des chaînes.

 // Définir un élément 
stockage local .  setItem  ( "nom"   "Leigh" ) ; 

 // Obtenir un élément .
localStorage .  getItem  ( "nom" ) ;   // "Leigh" 

 // Si nous regardons `stockage local`, nous voyons: 
 // Stockage {nom: "Leigh", longueur: 1} 

 // nous pouvons supprimer un élément individuel: 
localStorage .  removeItem  ( "name" ) ; 

 // Ou nous pouvons effacer tous les éléments: 
localStorage .  clear  () ; 

J'ai mentionné que la clé et la valeur doivent être des chaînes … alors, comment stockons-nous un tableau ou un objet? Nous pouvons le faire en utilisant JSON.stringify (objet) pour convertir notre objet JS en chaîne JSON lors de la définition de l'élément et utiliser JSON.parse (chaîne) pour convertir la chaîne JSON. retour dans un objet JS lors de l'obtention de l'élément. Regardez l'exemple ci-dessous:

 let  user  =   { nom :   "Leigh"  email :   "leigh@email.com"  } ; 

 // Doit être clarifié avant de ranger un objet 
stockage local .  setItem  ( "utilisateur"  JSON .  stringify  ( utilisateur ) (19659016) ) ; 

 // Doit être analysé lors de la lecture d'une valeur de chaîne dans la mémoire 
utilisateur  =  JSON .  parse  ( localStorage .  getItem  ( "utilisateur" )  ) ; 

Si vous lisez un article de LocalStorage et qu'il ressemble à "[object Object]," c'est le signe que vous avez oublié de hiérarchiser la valeur en premier!

Cookies

Si votre application est un SPA (application d'une seule page) entièrement côté client, vous n'avez probablement pas besoin de manipuler les cookies, et localStorage fera l'affaire. Cela dit, si vous utilisez quelque chose comme Next.js pour prendre en charge le rendu côté serveur (SSR), les cookies deviennent très importants et vous donnent accès au jeton d'authentification sur le serveur.

Nous pensons généralement aux cookies au pluriel. , mais la vérité est qu’elles sont stockées dans une seule valeur de chaîne qui doit être analysée pour pouvoir les diviser en paires clé / valeur individuelles.

 console .  log  ( document . .]  cookies ) ; 
 // « AMCV_A783776A5245B1E50A490D44% 40AdobeOrg = 2121618341% 7CMCIDTS% 7C17913% 7CMCMID% 7C60111815297468236860711566255111819255% 7CMCAAMLH-1548272641% 7C9% 7CMCAAMB-1548272641% 7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y% 7CMCOPTOUT-1547675041s% 7CNONE% 7CMCAID% 7CNONE; _gcl_au = 1.1.664470253.1547667842, jeton = eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbiI6IjY3Njc2N2VkLTFkYTMtNGZjOS05OGYxLTc3YTJlYjUzZGFlOSJ9.0BwIIJdHXmP_MLh5qQjUpdWZ_IQ4bjb6aSsTetLA_N4" 

C'est un gâchis! Nous pouvons les séparer en scindant la chaîne dans ";" et si nous cartographions ensuite chaque valeur et la scindons dans "=" nous aurons finalement la clé / paires de valeurs que nous recherchons:

 const  cookies  =  document .  cookie .  divisé  (.  "[;) .  carte  ( valeur  =>  valeur .  divisée  ( "="  ) ) ; 
 // nous donne: 
 [
   [
     "AMCV_A783776A5245B1E50A4roblocage de matériel et de matériel de qualité % 7CMCAAMLH-1548272641% 7C9% 7CMCAAMB-1548272641% 7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y% 7CMCOPTOUT-1547675041s% 7CNONE% 7CMCAID% 7CNONE "
  ] 
   [" _ gcl_au " " 1.1 .664470253.1547667842 "] [19659095] [
     "jeton" 
     "eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbiI6IjY3Njc2N2VkLTFkYTMtNGZjOS05OGYxLTc3YTJlYjUzZGFlOSJ9.0BwIIJdHXmP_MLh5qQjUpdWZ_IQ4bjb6aSsTetLA_N4" 
  ] 
] ; 

Le dernier biscuit, nous pouvons voir est le jeton cookie, qui stocke le JWT (Token Web JSON) requis pour l'authentification.

Lire et écrire des cookies dans ce format – nous n’avons même pas couvert les valeurs d’expiration et de codage / décodage – est une très grosse douleur et pourquoi une petite bibliothèque comme js-cookie peut vous faciliter la vie.

Avec js-cookie, nous pouvons obtenir et installer des cookies de la même manière que nous l'avons fait. it with localStorage:

 // définit une valeur 
jsCookie .  set  ( "nom"   "Leigh" ) ; 

 // Obtenir une valeur .
jsCookie .  get  ( "nom" ) ;   // "Leigh" 

 // supprimer le cookie 
jsCookie .  remove  ( "nom" )  

Il convient de mentionner que certains cookies peuvent être marqués comme "HTTP uniquement", ce qui signifie qu'ils ne sont pas accessibles depuis le code JavaScript côté client. Les cookies peuvent également avoir une date d'expiration, être limités à un certain sous-domaine et / ou chemin, et être uniquement disponibles sur des connexions sécurisées (HTTPS).

Authentification à l'aide d'un JWT

Grâce à notre nouvelle connaissance de localStorage, sessionStorage, et cookies, implémentons un composant de connexion qui envoie une requête HTTP au serveur avec l’adresse électronique et le mot de passe de l’utilisateur, et reçoit une réponse avec un jeton JWT s’il est valide. Lorsque nous aurons le jeton JWT, nous devrons le stocker quelque part. Vous devez maintenant choisir entre le stockage local ou les cookies, mais comme nous le faisons depuis une application Next.js qui prend en charge le SSR, nous devrons choisir le stockage des cookies de manière à ce qu'il soit disponible pour le serveur. 19659004] Pour mieux encapsuler notre logique d'authentification, nous allons créer un crochet personnalisé appelé useAuth chargé de générer la demande HTTP et de suivre ce que l'utilisateur a saisi dans le formulaire.

 // Dans les pages / login.js 

const useAuth = () => {
// Il est obligatoire de suivre les données du formulaire
const ] [ soumettant setSubmitting ] = useEtat ( false ) ;
[1965916] email setEmail ] = useEtat ( "" ) ;
const [ mot de passe setPassword ] = useState ( "" ) ;
const [ erreur setError ] = useState ( "" ) ;

// Une fonction à appeler lorsque l'utilisateur est prêt à authentifier
// les valeurs entrées dans le formulaire.
const authenticate = événement asynchrone => {
    événement . preventDefault () ;
setSubmitting ( true ) ;
des suivants:
19659017] "" ) ;

try {
// Envoyez une requête HTTP au serveur
const response = wait Axios . post (
"https://leigh-notes-api.herokuapp.com/session"
{
          courriel
          mot de passe
        }
) ;
// Passez le jeton à une fonction `login` qui est responsable
// pour avoir sauvegardé sa valeur dans un cookie et redirigé l'utilisateur.
const { jeton } = réponse . données ;
login ( {. ]} ) ;
} capture ( erreur ) {
// Un mot "invalide" comme mot de passe ou mot de passe invalide. utilisateur
// peut voir le message d'erreur.
if ( erreur . réponse && erreur . réponse




Source link