Gestion de CORS dans Express

Comment autoriser les demandes intersites en configurant CORS

Une application JavaScript exécutée dans le navigateur ne peut généralement accéder aux ressources HTTP qu'à partir du même domaine (origine) qui les sert.

Le chargement d'images ou de scripts / styles de la même origine fonctionne toujours. En outre, charger des polices Web à l'aide de@font-faceont la politique de «même origine» définie par défaut. De même avec d'autres choses moins populaires (comme les textures WebGL etdrawImageressources chargées dans l'API Canvas).

Cependant, les appels XHR et Fetch vers un serveur tiers externe échoueront. À moins que le serveur tiers n'implémente un mécanisme permettant d'établir la connexion et de télécharger et d'utiliser les ressources demandées.

Ce mécanisme s'appelleCORS,Partage de ressources inter-origines.

Une chose très importante qui a besoin de CORS estModules ES, récemment introduit dans les navigateurs modernes.

Si vous ne configurez pas de politique CORSsur le serveurqui lui permet de servir des origines tierces, la demande échouera.

Exemple de récupération:

Fetch failed because of CORS policy

Exemple XHR:

XHR request failed because of CORS policy

Une ressource Cross-Origin échoue si c'est:

  • à un autredomaine
  • à un autresous-domaine
  • à un autrePort
  • à un autreprotocole

CORS est là pour votre sécurité, pour empêcher les utilisateurs malveillants d'exploiter la plate-forme Web que vous utilisez.

Si vous contrôlez à la fois le serveuretle client, vous savez que les deux parties sont dignes de confiance, et ont donc de bonnes raisons d'autoriser le partage des ressources.

Comment?

Cela dépend de votre pile côté serveur.

Prise en charge du navigateur

Assez bien (essentiellement tous sauf IE <10):

CORS browser support

Exemple avec Express

Si vous utilisez Node.js et Express comme framework, utilisez lePackage middleware CORS.

Voici une implémentation simple d'un serveur Express Node.js:

const express = require('express')
const app = express()

app.get(’/without-cors’, (req, res, next) => { res.json({ msg: ‘😞 no CORS, no party!’ }) })

const server = app.listen(3000, () => { console.log(‘Listening on port %s’, server.address().port) })

Si vous frappez/without-corsavec une demande de récupération d'une origine différente, cela va soulever le problème CORS.

Tout ce que vous devez faire pour que les choses fonctionnent correctement est d'exigercorspackage lié ci-dessus et transmettez-le en tant que fonction middleware à un gestionnaire de requêtes de point de terminaison:

const express = require('express')
const cors = require('cors')
const app = express()

app.get(’/with-cors’, cors(), (req, res, next) => { res.json({ msg: ‘WHOAH with CORS it works! 🔝 🎉’ }) })

/* the rest of the app */

J'ai fait un exemple simple de Glitch, voici son code:https://glitch.com/edit/#!/flavio-cors-client.

Voici le serveur Node.js Express:https://glitch.com/edit/#!/flaviocopes-cors-example-express

Notez comment la demande qui échoue, car le serveur ne gère pas correctement les en-têtes CORS, est toujours reçue. Comme vous pouvez le voir dans le panneau Réseau, où vous pouvez voir un message envoyé par le serveur:

No response from CORS

Autoriser uniquement des origines spécifiques

Cet exemple présente cependant un problème: TOUTE demande sera acceptée par le serveur comme origine croisée.

Comme vous pouvez le voir dans le panneau Réseau, la demande qui a passé a un en-tête de réponseaccess-control-allow-origin: *:

The CORS response header

Vous devez configurer le serveur pour n'autoriser qu'une seule origine à servir et bloquer toutes les autres.

En utilisant le mêmecorsBibliothèque de nœuds, voici comment procéder:

const cors = require('cors')

const corsOptions = { origin: https://yourdomain.com, }

app.get(’/products/:id’, cors(corsOptions), (req, res, next) => { //… })

Vous pouvez également en servir plus:

const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
}

Contrôle en amont

Certaines demandes sont traitées de manière «simple». ToutGETles demandes appartiennent à ce groupe.

Égalementquelques POSTetHEADles demandes le font aussi.

POSTles demandes sont également dans ce groupe, si elles satisfont à l'exigence d'utiliser un Content-Type de

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Toutes les autres demandes doivent passer par une phase de pré-approbation, appelée contrôle en amont. Le navigateur le fait pour déterminer s'il a l'autorisation d'effectuer une action, en émettant unOPTIONSdemander.

Une demande de contrôle en amont contient quelques en-têtes que le serveur utilisera pour vérifier les autorisations (champs non pertinents omis):

OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.com

The server will respond with something like this (irrelevant fields omitted):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE

We checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.

Following the Node.js Express example above, the server must also handle the OPTIONS request:

var express = require('express')
var cors = require('cors')
var app = express()

//allow OPTIONS on just one resource app.options(’/the/resource/you/request’, cors())

//allow OPTIONS on all resources app.options(’*’, cors())

Download my free Express.js Handbook


More express tutorials: