CORS: impossible d'utiliser le caractère générique dans Access-Control-Allow-Origin lorsque l'indicateur d'informations d'identification est vrai

296

J'ai une configuration impliquant

Serveur frontal (Node.js, domaine: localhost: 3000) <---> Backend (Django, Ajax, domaine: localhost: 8000)

Navigateur <- webapp <- Node.js (servir l'application)

Navigateur (webapp) -> Ajax -> Django (Servir les requêtes POST ajax)

Maintenant, mon problème ici est avec la configuration CORS que la webapp utilise pour passer des appels Ajax au serveur principal. En chrome, je continue de

Impossible d'utiliser le caractère générique dans Access-Control-Allow-Origin lorsque l'indicateur d'informations d'identification est vrai.

ne fonctionne pas non plus sur Firefox.

Ma configuration Node.js est:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:8000/');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
};

Et dans Django j'utilise ce middleware avec cela

La webapp fait des demandes en tant que telles:

$.ajax({
    type: "POST",
    url: 'http://localhost:8000/blah',
    data: {},
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    dataType: 'json',
    success: successHandler
});

Ainsi, les en-têtes de demande envoyés par la webapp ressemblent à:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE'
Content-Type: application/json 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=***; sessionid="***"

Et voici l'en-tête de réponse:

Access-Control-Allow-Headers: Content-Type,*
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Type: application/json

Où vais-je me tromper?!

Edit 1: J'ai utilisé chrome --disable-web-security, mais je veux maintenant que les choses fonctionnent réellement.

Edit 2: Réponse:

Donc, solution pour moi django-cors-headersconfig:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000' # Here was the problem indeed and it has to be http://localhost:3000, not http://localhost:3000/
)
ixaxaar
la source
1
Pour moi, c'est localhost: 3000 sans http, comme ceci: CORS_ORIGIN_WHITELIST = ('localhost: 3000',)
Andrei
Voulez-vous dire que vous utilisez développer le frontend et le backend sur un seul PC?
fanhualuojin154873
que diriez-vous du frontend et du backend dans différents PC?
fanhualuojin154873
@ixaxaar pourquoi vous dites que http fonctionne pour vous? nous ne travaillons tous que `` localhost: 3000 ''.
244boy
@ 244boy ouais le point n'est pas le http, c'est le /à la fin. Je suppose qu'omettre http pourrait fonctionner, mais je n'ai pas vraiment travaillé sur ce genre de choses depuis quelques années, donc je ne sais pas vraiment ce qui fonctionne maintenant!
ixaxaar

Réponses:

247

Cela fait partie de la sécurité, vous ne pouvez pas le faire. Si vous souhaitez autoriser les informations d'identification, vous Access-Control-Allow-Originne devez pas les utiliser *. Vous devrez spécifier le protocole + domaine + port exact. Pour référence, voir ces questions:

  1. Sous-domaines, ports et protocoles génériques Access-Control-Allow-Origin
  2. Partage de ressources d'origine croisée avec informations d'identification

En outre, il *est trop permissif et irait à l'encontre de l'utilisation des informations d'identification. Définissez donc http://localhost:3000ou http://localhost:8000comme en-tête d'origine autorisé.

user568109
la source
45
Mais que faire s'il y a plus d'un domaine?
2014
13
@aroth Vous pouvez donner une liste de domaines. Question connexe: stackoverflow.com/questions/1653308/…
user568109
13
@ user568109 Pourriez-vous expliquer "De plus, *c'est trop permissif et cela irait à l'encontre de l' utilisation des informations d'identification".
Hugo Wood
12
Quel est le "domaine exact" si la demande provient d'un appareil mobile, comme cela peut arriver avec Cordova?
Christian
8
@Christian un peu vieux, mais si quelqu'un reste curieux, ce problème ne se produit que pour les applications exécutées sur les navigateurs, car cette erreur est générée par le navigateur pour des raisons de sécurité. D'autres clients tels qu'une application mobile, un facteur ou tout autre code backend utilisant le client http pour faire une demande n'auront pas ce problème, vous n'avez donc pas à vous soucier de l'origine et du domaine exact .
Alisson
32

Si vous utilisez un middleware CORS et que vous souhaitez envoyer un withCredentialbooléen true, vous pouvez configurer CORS comme ceci:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));
Hamid
la source
16

Si vous utilisez, expressvous pouvez utiliser le package cors pour autoriser CORS comme tel au lieu d'écrire votre middleware;

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

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});
Bulkan
la source
12
Ah, maintenant c'est plus pratique, cependant, le résultat est le même :( BTW, j'utiliseapp.use(cors({credentials: true}));
ixaxaar
1
Vous voudrez peut-être examiner ce middleware Django CORS qui est testé.
Bulkan
1
Vous avez donc deux middlewares Django? Je n'utiliserais que l' django-cors-headerapplication. Assurez-vous d'ajouter localhost au CORS_ORIGIN_WHITELISTparamètre et de le définir CORS_ALLOW_CREDENTIALSsurTrue
Bulkan
1
Ouais mec, j'ai essayé ça avant en vain CORS_ORIGIN_ALLOW_ALL = True, CORS_ORIGIN_WHITELIST = ( 'localhost' )etCORS_ALLOW_CREDENTIALS = True j'ai j'ai ces en-têtes:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:3000/ Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE Content-Type: application/json
ixaxaar
5
Après avoir lu cette documentation: github.com/expressjs/corsuse i utilisant cette config: app.use (cors ({credentials: true, origin: ' localhost: 3001 '})); travaille pour moi.
allel
11

essayez-le:

const cors = require('cors')

const corsOptions = {
    origin: 'http://localhost:4200',
    credentials: true,

}
app.use(cors(corsOptions));
Bouclier de fer
la source
6

Si vous souhaitez autoriser toutes les origines et conserver les informations d'identification vraies, cela a fonctionné pour moi:

app.use(cors({
  origin: function(origin, callback){
    return callback(null, true);
  },
  optionsSuccessStatus: 200,
  credentials: true
}));
Squirrl
la source
@TSlegaitis Haha ouais c'est pourquoi cela fonctionne pour toutes les origines mais conserve les informations d'identification. Je ne le recommanderais pas pour la sécurité mais cela fonctionne.
Squirrl
2

(Modifier) ​​Le module complémentaire précédemment recommandé n'est plus disponible, vous pouvez essayer cet autre


À des fins de développement dans Chrome, l'installation de ce module complémentaire supprimera cette erreur spécifique:

Access to XMLHttpRequest at 'http://192.168.1.42:8080/sockjs-node/info?t=1546163388687' 
from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 
'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 
when the request's credentials mode is 'include'. The credentials mode of requests 
initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Après l'installation, assurez-vous d'ajouter votre modèle d'URL Intercepted URLsen cliquant sur l' icône AddOn ( CORS , vert ou rouge) et en remplissant la zone de texte appropriée. Un exemple de modèle d'URL à ajouter ici qui fonctionnera http://localhost:8080serait:*://*

eriel marimon
la source
Je l'ai eu juste après l'avoir installé, des idées?
Jalil
Ça a marché pour moi. Attention si vous avez d'autres modules complémentaires similaires, vous devez le désinstaller avant d'essayer celui-ci.
FilippoG
veuillez corriger le lien brisé
Luk Aron
On dirait que l'add-on d'origine a été supprimé, j'ai ajouté une nouvelle recommandation en tant que (Modifier) ​​en haut
eriel marimon
1

Cela fonctionne pour moi en développement, mais je ne peux pas dire qu'en production, c'est juste une manière différente de faire le travail qui n'a pas encore été mentionnée mais probablement pas la meilleure. Quoi qu'il en soit, voici:

Vous pouvez obtenir l'origine de la demande, puis l'utiliser dans l'en-tête de réponse. Voici à quoi cela ressemble en express:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', req.header('origin') );
  next();
});

Je ne sais pas à quoi cela ressemblerait avec votre configuration python mais cela devrait être facile à traduire.

Renaud
la source
Mozilla Dev Docs développe l'idée de changer l'origine autorisée à celle de la demande. Il est suggéré d'ajouter un en-tête de réponse HTTP «Vary: Origin» et une liste blanche de domaines autorisés.
Ramzis