diff --git a/6-data-storage/01-cookie/article.md b/6-data-storage/01-cookie/article.md index 01c0e1fee..2827adf2b 100644 --- a/6-data-storage/01-cookie/article.md +++ b/6-data-storage/01-cookie/article.md @@ -1,80 +1,78 @@ # Cookies, document.cookie -Cookies are small strings of data that are stored directly in the browser. They are a part of the HTTP protocol, defined by the [RFC 6265](https://tools.ietf.org/html/rfc6265) specification. +Les cookies sont des donnés stockées sous forme de petites chaîne de caractères directement dans le navigateur. Ils font parti du protocole HTTP, ils sont définis par la spécification [RFC 6265](https://tools.ietf.org/html/rfc6265). -Cookies are usually set by a web-server using the response `Set-Cookie` HTTP-header. Then, the browser automatically adds them to (almost) every request to the same domain using the `Cookie` HTTP-header. +Les cookies sont en général définis par le serveur web en utilisant l'entête HTTP `Set-Cookie`. Alors, le navigateur les ajoutent automatiquement à (presque) toutes les requêtes provenant du même domaine en utilisant l'entête HTTP `Cookie`. -One of the most widespread use cases is authentication: +L'un des cas d'utilisation les plus répandus est l'authentification : -1. Upon sign in, the server uses the `Set-Cookie` HTTP-header in the response to set a cookie with a unique "session identifier". -2. Next time when the request is sent to the same domain, the browser sends the cookie over the net using the `Cookie` HTTP-header. -3. So the server knows who made the request. +1. Une fois connecté, le serveur utilise l'entête HTTP `Set-Cookie` dans la réponse pour définir un cookie avec un "identifiant de session" unique. +2. La prochaine fois lorsque la requête est envoyée au même domaine, le navigateur envoie le cookie sur le réseau en utilisant l'entête HTTP `Cookie`. +3. Alors le serveur sait qui a fait la requête. -We can also access cookies from the browser, using `document.cookie` property. +Nous pouvons aussi accéder aux cookies depuis le navigateur, en utilisant la propriété `document.cookie`. -There are many tricky things about cookies and their options. In this chapter we'll cover them in detail. +Il y a beaucoup de chose malignes à faire à propos des cookies et leurs options. Dans ce chapitre nous les couvrirons en détail. -## Reading from document.cookie +## Lire depuis document.cookie ```online -Does your browser store any cookies from this site? Let's see: +Votre navigateur stocke t-il des cookies depuis ce site ? Voyons voir : ``` ```offline -Assuming you're on a website, it's possible to see the cookies from it, like this: +En considérant que vous êtes sur un site web, il est possible de voir ses cookies, comme ceci : ``` ```js run -// At javascript.info, we use Google Analytics for statistics, -// so there should be some cookies +// Sur javascript.info, nous utilisons Google Analytics pour les statistiques, +// Donc il devrait y avoir quelques cookies alert( document.cookie ); // cookie1=value1; cookie2=value2;... ``` +La valeur de `document.cookie` consiste en des paires `name=value`, délimitées par `; `. Chacune étant un cookie séparé. -The value of `document.cookie` consists of `name=value` pairs, delimited by `; `. Each one is a separate cookie. +Pour trouver un cookie en particulier, nous pouvons diviser `document.cookie` par `; `, et donc trouver le bon nom. Nous pouvons utiliser soit une expression régulière (regex) ou des fonctions de tableau pour faire cela. -To find a particular cookie, we can split `document.cookie` by `; `, and then find the right name. We can use either a regular expression or array functions to do that. +Nous laissons cela en tant qu'exercice pour le lecteur. Aussi, à la fin du chapitre vous trouverez des fonctions utilitaires pour manipuler les cookies. -We leave it as an exercise for the reader. Also, at the end of the chapter you'll find helper functions to manipulate cookies. +## Écrire dans document.cookie -## Writing to document.cookie +Nous pouvons écrire dans `document.cookie`. Mais ce n'est pas une propriété de données, c'est un [accesseur (getter/setter)](info:property-accessors). Une affectation à ce dernier est traitée spécialement. -We can write to `document.cookie`. But it's not a data property, it's an [accessor (getter/setter)](info:property-accessors). An assignment to it is treated specially. +**Une opération d'écriture dans `document.cookie` met à jour seulement les cookies mentionnés dedans, mais ne touche pas les autres cookies.** -**A write operation to `document.cookie` updates only cookies mentioned in it, but doesn't touch other cookies.** - -For instance, this call sets a cookie with the name `user` and value `John`: +Par exemple, cet appel définit un cookie avec le nom `user` et la valeur `John` : ```js run -document.cookie = "user=John"; // update only cookie named 'user' -alert(document.cookie); // show all cookies +document.cookie = "user=John"; // Met à jour uniquement le cookie nommé 'user' +alert(document.cookie); // Affiche tous les cookies ``` -If you run it, then probably you'll see multiple cookies. That's because the `document.cookie=` operation does not overwrite all cookies. It only sets the mentioned cookie `user`. +Si vous exécutez cela, vous verrez probablement plusieurs cookies. Car l'opération `document.cookie=` ne réécrit pas tous les cookies. Elle définit uniquement le cookie `user` mentionné. -Technically, name and value can have any characters. To keep the valid formatting, they should be escaped using a built-in `encodeURIComponent` function: +Techniquement, le nom et la valeur peuvent être n'importe quel caractère. Pour garder le formattage valide, ils devraient être échappés en utilisant la fonction integrée `encodeURIComponent` : ```js run -// special characters (spaces), need encoding +// Les caractères spéciaux ont besoin d'encodage let name = "my name"; let value = "John Smith" -// encodes the cookie as my%20name=John%20Smith +// Encode le cookie en tant que my%20name=John%20Smith document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); alert(document.cookie); // ...; my%20name=John%20Smith ``` - ```warn header="Limitations" -There are few limitations: -- The `name=value` pair, after `encodeURIComponent`, should not exceed 4KB. So we can't store anything huge in a cookie. -- The total number of cookies per domain is limited to around 20+, the exact limit depends on the browser. +Il y a quelques limites : +- La paire `name=value`, après `encodeURIComponent`, ne peut pas excéder 4KB. Donc on ne peut pas stocker quelque chose de trop lourd sur un cookie. +- Le nombre total de cookie par domaine est limité à ~ 20+, la limite exacte dépend du navigateur. ``` -Cookies have several options, many of them are important and should be set. +Les cookies ont plusieurs options, beaucoup d'entre elles sont importantes et devraient être définies. -The options are listed after `key=value`, delimited by `;`, like this: +Les options sont listées après `key=value`, délimité par `;`, comme ceci : ```js run document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT" @@ -84,87 +82,87 @@ document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT" - **`path=/mypath`** -The url path prefix must be absolute. It makes the cookie accessible for pages under that path. By default, it's the current path. +Le préfix du chemin de l'URL doit être absolu. Ça rend le cookie accessible pour les pages du même chemin. Par défaut, il s'agit du chemin courant. -If a cookie is set with `path=/admin`, it's visible at pages `/admin` and `/admin/something`, but not at `/home` or `/adminpage`. +Si un cookie est défini avec `path=/admin`, il est visible aux pages `/admin` et `/admin/something`, mais pas à `/home` ou `/adminpage`. -Usually, we should set `path` to the root: `path=/` to make the cookie accessible from all website pages. +Généralement, nous devons définir `path` à la racine `path=/` pour rendre le cookie accessible depuis toutes les pages du site. ## domain - **`domain=site.com`** -A domain defines where the cookie is accessible. In practice though, there are limitations. We can't set any domain. +Un domaine définit par où le cookie est accessible. Cependant en pratique, il y a des limites. Nous ne pouvons pas définir n'importe quel domaine. -**There's no way to let a cookie be accessible from another 2nd-level domain, so `other.com` will never receive a cookie set at `site.com`.** +**Il n'y a pas de moyen de laisser un cookie être accessible depuis un domaine de second niveau, donc `other.com` ne recevra jamais un cookie défini à `site.com`** -It's a safety restriction, to allow us to store sensitive data in cookies that should be available only on one site. +Il s'agit d'une restriction de sécurité, pour nous permettre de stocker des données sensibles dans nos cookies qui ne seront disponibles que sur un site. -By default, a cookie is accessible only at the domain that set it. +Par défaut, un cookie est accessible uniquement depuis le domaine qui l'a défini. -Please note, by default a cookie is also not shared to a subdomain as well, such as `forum.site.com`. +Veuillez noter, par défaut un cookie n'est pas partagé avec un sous-domaine, tel que `forum.site.com`. ```js -// if we set a cookie at site.com website... +// Si nous définissons un cookie sur site.com document.cookie = "user=John" -// ...we won't see it at forum.site.com +// ...Nous ne le verrons pas depuis forum.site.com alert(document.cookie); // no user ``` -...But this can be changed. If we'd like to allow subdomains like `forum.site.com` to get a cookie set at `site.com`, that's possible. +...Mais cela peut changer. Si nous aimerions permettre aux sous-domaines comme `forum.site.com` de récupérer un cookie défini par `site.com`, c'est possible. -For that to happen, when setting a cookie at `site.com`, we should explicitly set the `domain` option to the root domain: `domain=site.com`. Then all subdomains will see such cookie. +Pour que cela arrive, quand nous definissons un cookie depuis `site.com`, nous pouvons définir l'option `domain` à la racine du domaine : `domain=site.com`. Alors tous les sous-domaines verront un tel cookie. -For example: +Par exemple : ```js -// at site.com -// make the cookie accessible on any subdomain *.site.com: +// Depuis site.com +// Rendre le cookie accessible à tous les sous-domaines *.site.com: document.cookie = "user=John; *!*domain=site.com*/!*" -// later +// Plus tard -// at forum.site.com -alert(document.cookie); // has cookie user=John +// Depuis forum.site.com +alert(document.cookie); // Le cookie user=John existe ``` -For historical reasons, `domain=.site.com` (with a dot before `site.com`) also works the same way, allowing access to the cookie from subdomains. That's an old notation and should be used if we need to support very old browsers. +Pour des raisons historiques, `domain=.site.con` (avec un point avant `site.com`) fonctionne de la même manière, permettant l'accés au cookie depuis les sous-domaines. C'est une vielle notation et devrait être utilisée si nous avons besoin de prendre en charge les très vieux navigateurs. -To summarize, the `domain` option allows to make a cookie accessible at subdomains. +Pour résumer, l'option `domain` permet de rendre un cookie accessible aux sous-domaines. ## expires, max-age -By default, if a cookie doesn't have one of these options, it disappears when the browser is closed. Such cookies are called "session cookies" +Par défaut, si un cookie n'a pas ces options, il disparait quand le navigateur est fermé. De tels cookies sont appellés "cookies de session" -To let cookies survive a browser close, we can set either the `expires` or `max-age` option. +Pour laisser les cookies survivre à la fermeture du navigateur, nous pouvons soit définir soit l'option `expires` ou `max-age`. - **`expires=Tue, 19 Jan 2038 03:14:07 GMT`** -The cookie expiration date defines the time, when the browser will automatically delete it. +La date d'expiration du cookie définit la date, à laquelle le navigateur le supprimera automatiquement. -The date must be exactly in this format, in the GMT timezone. We can use `date.toUTCString` to get it. For instance, we can set the cookie to expire in 1 day: +La date doit être exactement dans ce format, en timezone GMT. Nous pouvons utiliser `date.toUTCString` pour le récupérer. Par exemple, nous pouvons définir le cookie pour qu'il expire dans 1 jour : ```js -// +1 day from now +// +1 jour depuis maintenant let date = new Date(Date.now() + 86400e3); date = date.toUTCString(); document.cookie = "user=John; expires=" + date; ``` -If we set `expires` to a date in the past, the cookie is deleted. +Si nous définissons `expires` à une date dans le passé, le cookie est supprimé. -- **`max-age=3600`** +- **`max-age=3600`** -It's an alternative to `expires` and specifies the cookie's expiration in seconds from the current moment. +Il s'agit d'une alternative à `expires` et elle spécifie l'expiration du cookie en seconde à partir de l'instant. -If set to zero or a negative value, the cookie is deleted: +Si elle est définie à zero ou une valeur négative, le cookie sera supprimé : ```js -// cookie will die in +1 hour from now +// Le cookie mourra dans +1 heure à partir de maintenant document.cookie = "user=John; max-age=3600"; -// delete cookie (let it expire right now) +// Supprime le cookie (le laisser expirer tout de suite) document.cookie = "user=John; max-age=0"; ``` @@ -172,125 +170,123 @@ document.cookie = "user=John; max-age=0"; - **`secure`** -The cookie should be transferred only over HTTPS. +Le cookie devrait être transféré seulement avec HTTPS. -**By default, if we set a cookie at `http://site.com`, then it also appears at `https://site.com` and vice versa.** +**Par défaut, si nous définissons un cookie à `http://site.com`, alors il apparaitra aussi à `https://site.com` et vice versa.** -That is, cookies are domain-based, they do not distinguish between the protocols. +Les cookies sont "domain-based", ils ne sont pas distinguables entre les protocoles. -With this option, if a cookie is set by `https://site.com`, then it doesn't appear when the same site is accessed by HTTP, as `http://site.com`. So if a cookie has sensitive content that should never be sent over unencrypted HTTP, the `secure` flag is the right thing. +Avec cette option, si un cookie est défini par `https://site.com`, alors il n'apparait pas quand le même site est accédé par HTTP, comme `http://site.com`. Donc si un cookie a un contenu sensible il ne devrait pas être envoyé sur HTTP qui n'est chiffré, le flag `secure` est la bonne chose. ```js -// assuming we're on https:// now -// set the cookie to be secure (only accessible over HTTPS) +// Considérons que nous soyons sur https:// maintenant +// Définit le cookie pour être sécurisé (seulement accessible par HTTPS) document.cookie = "user=John; secure"; ``` ## samesite -That's another security attribute `samesite`. It's designed to protect from so-called XSRF (cross-site request forgery) attacks. - -To understand how it works and when it's useful, let's take a look at XSRF attacks. +Il s'agit d'un nouvel attribut de sécurité `samesite`. Il a été conçu pour protéger de ce qu'on appelle attaques XSRF (cross-site request forgery). -### XSRF attack +## L'attaque XSRF -Imagine, you are logged into the site `bank.com`. That is: you have an authentication cookie from that site. Your browser sends it to `bank.com` with every request, so that it recognizes you and performs all sensitive financial operations. +Imaginez, vous êtes connecté sur le site `bank.com`. Ce qui signifie : que vous avez un cookie d'authentification sur ce site. Votre navigateur l'envoie à `bank.com` à chaque requête, donc il vous reconnait et effectue toutes les opérations financières sensibles. -Now, while browsing the web in another window, you accidentally come to another site `evil.com`. That site has JavaScript code that submits a form `
` to `bank.com` with fields that initiate a transaction to the hacker's account. +Maintenant, pendant que vous naviguez sur le web dans une autre fenêtre, vous arrivez accidentellement sur un autre site `evil.com`. Ce site a du code JavaScript qui soumet un formulaire `` à `bank.com` avec les champs qui initient une transaction avec le compte du hacker. -The browser sends cookies every time you visit the site `bank.com`, even if the form was submitted from `evil.com`. So the bank recognizes you and actually performs the payment. +Le navigateur envoie des cookies à chaque fois que vous visitez le site `bank.com`, même si le formulaire a été envoyé depuis `evil.com`. Donc la banque vous reconnait et effectue le paiement. ![](cookie-xsrf.svg) -That's a so-called "Cross-Site Request Forgery" (in short, XSRF) attack. +C'est ce qu'on appelle une attaque "Cross-Site Request Forgery" (XSRF en plus court). -Real banks are protected from it of course. All forms generated by `bank.com` have a special field, a so-called "XSRF protection token", that an evil page can't generate or extract from a remote page. It can submit a form there, but can't get the data back. The site `bank.com` checks for such token in every form it receives. +Les vraies banques en sont évidemment protégées. Tous les formulaires générés par `bank.com` ont un champ spécial, un certain "XSRF protection token", qu'une page malveillante ne peut pas générer ou extraire de la page distante. Elle peut y soumettre un formulaire, mais pas récupérer les données. Le site `bank.com` vérifie ce genre de token dans tous les formulaires qu'il reçoit. -Such a protection takes time to implement though. We need to ensure that every form has the required token field, and we must also check all requests. +Une telle protection prend du temps à mettre en œuvre cependant. Nous avons besoin de nous assurer que tous les formulaires ont le champ de token requis, et nous devons aussi vérifier toutes les requêtes. -### Enter cookie samesite option +### Entrer un cookie avec l'option samesite -The cookie `samesite` option provides another way to protect from such attacks, that (in theory) should not require "xsrf protection tokens". +L'option `samesite` de cookie fournit un autre moyen de se protéger de telles attaques, cela ne devrait (en théorie) pas nécessiter de "tokens de protections xsrf". -It has two possible values: +Elle a deux valeurs possible : -- **`samesite=strict` (same as `samesite` without value)** +- **`samesite=strict` (pareil que `samesite` sans valeur)** -A cookie with `samesite=strict` is never sent if the user comes from outside the same site. +Un cookie avec `samesite=strict` n'est jamais envoyé si un utilisateur vient d'en dehors du même site. -In other words, whether a user follows a link from their mail or submits a form from `evil.com`, or does any operation that originates from another domain, the cookie is not sent. +En d'autres termes, qu'importe que l'utilisateur suive un lien de ses mails ou soumette un formulaire provenant d'`evil.com`, ou qu'il fasse des opérations provenants d'un autre domaine, le cookie n'est pas envoyé. -If authentication cookies have the `samesite` option, then a XSRF attack has no chances to succeed, because a submission from `evil.com` comes without cookies. So `bank.com` will not recognize the user and will not proceed with the payment. +Si le cookie d'authentification a l'option `samesite`, alors l'attaque XSRF n'a aucune chance de se solder par un succés, car une soumission depuis `evil.com` ne vient pas avec les cookies. Donc `bank.com` ne reconnaitra pas l'utilisateur et ne procédera pas au paiement. -The protection is quite reliable. Only operations that come from `bank.com` will send the `samesite` cookie, e.g. a form submission from another page at `bank.com`. +La protection est plutôt fiable. Seules les opérations provenants de `bank.com` vont envoyer le cookie `samesite`, e.g. une soumission de formulaire depuis une autre page à `bank.com`. -Although, there's a small inconvenience. +Bien que, il y ait un petit inconvénient. -When a user follows a legitimate link to `bank.com`, like from their own notes, they'll be surprised that `bank.com` does not recognize them. Indeed, `samesite=strict` cookies are not sent in that case. +Quand un utilisateur suit un lien légitime vers `bank.com`, comme depuis ses propres notes, il sera surpris que `bank.com` ne le reconnaisse pas. En effet, les cookies `samesite=strict` ne sont pas envoyés dans ce cas. -We could work around that by using two cookies: one for "general recognition", only for the purposes of saying: "Hello, John", and the other one for data-changing operations with `samesite=strict`. Then, a person coming from outside of the site will see a welcome, but payments must be initiated from the bank's website, for the second cookie to be sent. +Nous pouvons contourner ça avec deux cookies : une pour la "reconnaissance générale", uniquement dans le but de dire : "Salut, John", et un autre pour les opérations de changements de données avec `samesite=strict`. Alors, une personne venant de l'extérieur du site verra un message de bienvenue, mais les paiements devront être initiés depuis le site de la banque, pour que le second cookie soit envoyé. - **`samesite=lax`** -A more relaxed approach that also protects from XSRF and doesn't break the user experience. +Une approche plus relax qui protège aussi des XSRF et qui n'entrave pas l'expérience utilisateur. -Lax mode, just like `strict`, forbids the browser to send cookies when coming from outside the site, but adds an exception. +Le mode lax, tout comme `strict`, interdit au navigateur d'envoyer des cookies quand venu de l'extérieur du site, mais ajoute une exception. -A `samesite=lax` cookie is sent if both of these conditions are true: -1. The HTTP method is "safe" (e.g. GET, but not POST). +Un cookie `samesite=lax` est envoyé lorsque deux conditions sont réunies : - The full list of safe HTTP methods is in the [RFC7231 specification](https://tools.ietf.org/html/rfc7231). Basically, these are the methods that should be used for reading, but not writing the data. They must not perform any data-changing operations. Following a link is always GET, the safe method. +1. La méthode HTTP est "safe" (e.g. GET, mais pas POST). -2. The operation performs a top-level navigation (changes URL in the browser address bar). + La liste complète des méthodes HTTP safes est dans la [spécification RFC7231](https://tools.ietf.org/html/rfc7231). Basiquement ce sont des méthodes qui peuvent être utilisées pour lire, mais pas pour écrire de données. Elles ne doivent pas effectuer d'opérations de modifications de données. Suivre un lien c'est toujours du GET, la méthode safe. - That's usually true, but if the navigation is performed in an `