CORS: impossibile utilizzare il carattere jolly in Access-Control-Allow-Origin quando il flag delle credenziali è true


296

Ho una configurazione che coinvolge

Server frontend (Node.js, dominio: localhost: 3000) <---> Backend (Django, Ajax, dominio: localhost: 8000)

Browser <- webapp <- Node.js (serve l'app)

Browser (webapp) -> Ajax -> Django (Servire richieste POST ajax)

Ora, il mio problema qui è con l'installazione CORS che la webapp utilizza per effettuare chiamate Ajax al server back-end. In cromo, continuo a ricevere

Impossibile utilizzare il carattere jolly in Access-Control-Allow-Origin quando il flag credenziali è true.

non funziona neanche su Firefox.

La mia configurazione di Node.js è:

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();
};

E in Django sto usando questo middleware insieme a questo

La webapp invia richieste in quanto tali:

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

Quindi, le intestazioni della richiesta che la webapp invia sembrano:

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="***"

Ed ecco l'intestazione della risposta:

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

Dove sto sbagliando ?!

Modifica 1: Sto usando chrome --disable-web-security, ma ora voglio che le cose funzionino davvero.

Modifica 2: Risposta:

Quindi, soluzione per me 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/
)

1
Per me è localhost: 3000 senza http, in questo modo: CORS_ORIGIN_WHITELIST = ('localhost: 3000',)
Andrei

Vuoi dire che usi sviluppare frontend e backend in un PC?
fanhualuojin154873,

che ne dici di frontend e backend su PC diversi?
fanhualuojin154873,

@ixaxaar perché dici che con http funziona per te? tutti noi lavoriamo solo con '' localhost: 3000 ''.
244boy,

@ 244boy sì, il punto non è il http, è il /alla fine. Suppongo che l'omissione di http potrebbe funzionare, ma non ho davvero lavorato su questa roba per alcuni anni, quindi non so davvero cosa funziona ora!
ixaxaar,

Risposte:


247

Questa è una parte della sicurezza, non puoi farlo. Se si desidera consentire le credenziali, Access-Control-Allow-Originnon è necessario utilizzare *. Dovrai specificare il protocollo esatto + dominio + porta. Per riferimento vedi queste domande:

  1. Sottodomini, porte e protocolli jolly Access-Control-Allow-Origin
  2. Condivisione delle risorse di origine incrociata con credenziali

Inoltre *è troppo permissivo e vanificherebbe l'uso delle credenziali. Quindi impostare http://localhost:3000o http://localhost:8000come intestazione di origine consentita.


45
E se ci fosse più di un dominio?
aroth

13
@aroth Puoi dare un elenco di domini. Questione connessa: stackoverflow.com/questions/1653308/...
user568109

13
@ user568109 Potresti spiegare "Inoltre *è troppo permissivo e vanificherebbe l' uso delle credenziali."?
Hugo Wood,

12
Qual è il "dominio esatto" se la richiesta proviene dal dispositivo mobile, come può accadere con Cordova?
Christian,

8
@Christian è un po 'vecchio, ma se qualcuno è ancora curioso, questo problema si verifica solo per le applicazioni in esecuzione sui browser, perché questo errore viene generato dal browser per motivi di sicurezza. Altri client come un'app mobile, un postino o qualsiasi altro codice back-end che utilizza il client http per effettuare una richiesta non avranno questo problema, quindi non devi preoccuparti dell'origine e del dominio esatto .
Alisson,

32

Se si utilizza il middleware CORS e si desidera inviare il valore withCredentialbooleano true, è possibile configurare CORS in questo modo:

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

16

Se stai usando expresspuoi usare il pacchetto cors per consentire CORS in questo modo invece di scrivere il tuo middleware;

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

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});

12
Ah, ora è più comodo, tuttavia, il risultato è lo stesso :( A proposito, sto usandoapp.use(cors({credentials: true}));
ixaxaar

1
Potresti voler esaminare questo middleware Django CORS che è stato testato.
Bulkan,

1
Quindi hai due middleware Django? Vorrei solo usare l' django-cors-headerapp. Assicurati di aggiungere localhost alle CORS_ORIGIN_WHITELISTimpostazioni e impostare CORS_ALLOW_CREDENTIALSsuTrue
Bulkan

1
Yeah man, provato che prima senza alcun risultato, ha avuto CORS_ORIGIN_ALLOW_ALL = True, CORS_ORIGIN_WHITELIST = ( 'localhost' )e CORS_ALLOW_CREDENTIALS = True io ottenere queste intestazioni: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
Dopo aver letto questa documentazione: github.com/expressjs/corsuse sto usando questo config: app.use (cors ({credenziali: vero, origine: ' localhost: 3001 '})); sta lavorando per me.
allel

11

Provalo:

const cors = require('cors')

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

}
app.use(cors(corsOptions));

6

Se vuoi consentire tutte le origini e mantenere vere le credenziali, questo ha funzionato per me:

app.use(cors({
  origin: function(origin, callback){
    return callback(null, true);
  },
  optionsSuccessStatus: 200,
  credentials: true
}));

@TSlegaitis Haha sì, è per questo che funziona per tutte le origini ma mantiene le credenziali. Non lo consiglierei per sicurezza ma funziona.
Squirrl,

2

(Modifica) Il componente aggiuntivo precedentemente raccomandato non è più disponibile, è possibile provare questo altro


Ai fini dello sviluppo in Chrome, l'installazione di questo componente aggiuntivo eliminerà l'errore specifico:

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.

Dopo l'installazione, assicurati di aggiungere il tuo pattern url al Intercepted URLsfacendo clic sull'icona di AddOn ( CORS , verde o rosso) e riempiendo la casella di testo appropriata. Un esempio di pattern URL da aggiungere qui che funzionerà http://localhost:8080sarebbe:*://*


L'ho preso subito dopo averlo installato, qualche idea?
Jalil,

Ha funzionato per me. Avviso se hai altri componenti aggiuntivi simili devi disinstallarlo prima di provare questo.
FilippoG,

correggi il link non funzionante
Luk Aron

Sembra che il componente aggiuntivo originale sia stato rimosso, ho aggiunto una nuova raccomandazione come (Modifica) in alto
eriel marimon

1

Questo funziona per me in fase di sviluppo, ma non posso consigliarlo in produzione, è solo un modo diverso di fare il lavoro che non è stato ancora menzionato ma probabilmente non è il migliore. Comunque qui va:

È possibile ottenere l'origine dalla richiesta, quindi utilizzarla nell'intestazione della risposta. Ecco come appare in express:

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

Non so come sarebbe con la configurazione di Python, ma dovrebbe essere facile da tradurre.


Mozilla Dev Docs si espande sull'idea di cambiare l'origine consentita in quella dalla richiesta. Si consiglia di aggiungere un'intestazione di risposta HTTP "Vary: Origin" e domini consentiti nella whitelist.
Ramzis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.