come bypassare Access-Control-Allow-Origin?


197

Sto facendo una chiamata Ajax al mio server su una piattaforma che hanno impostato per impedire queste chiamate Ajax (ma ne ho bisogno per recuperare i dati dal mio server per visualizzare i dati recuperati dal database del mio server). Il mio script ajax funziona, può inviare i dati allo script php del mio server per consentirne l'elaborazione. Tuttavia, non è possibile recuperare i dati elaborati poiché è bloccato da"Access-Control-Allow-Origin"

Non ho accesso al sorgente / core di quella piattaforma. quindi non riesco a rimuovere la sceneggiatura che mi impedisce di farlo. (P / SI ha utilizzato la console di Google Chrome e ha scoperto questo errore)

Il codice Ajax come mostrato di seguito:

 $.ajax({
     type: "GET",
     url: "http://example.com/retrieve.php",
     data: "id=" + id + "&url=" + url,
     dataType: 'json',   
     cache: false,
     success: function(data)
      {
        var friend = data[1];              
        var blog = data[2];           
        $('#user').html("<b>Friends: </b>"+friend+"<b><br> Blogs: </b>"+blog);

      } 
  });

o c'è un JSONcodice equivalente allo script ajax sopra? Penso che JSONsia permesso.

Spero che qualcuno mi possa aiutare.


tutte le risposte alla tua domanda finora hanno spiegato un modo per riscrivere il codice del tuo server in modo che Ajax funzioni. Nessuno di questi riguarda l'esclusione, come hai chiesto specificamente nella tua domanda. Hai trovato comunque di aggirare effettivamente questa intestazione? Dubito davvero che ce ne sarebbe uno.
Moradnejad,

non c'è modo di superarlo. ma è possibile inserire un file nel back-end che esegue la richiesta. Quindi chiami per ajax il file sul tuo server, quel file carica i dati da retrieve.php e li rimanda al tuo javascript. In tal caso non ci sono regole CORS che ti bloccano.
Jona Paulus,

Risposte:


367

Metti questo in cima a retrieve.php:

header('Access-Control-Allow-Origin: *');  

Nota che ciò disabilita efficacemente la protezione CORS e lascia gli utenti esposti agli attacchi. Se non sei completamente sicuro di dover consentire tutte le origini, dovresti bloccarlo a un'origine più specifica:

header('Access-Control-Allow-Origin: https://www.example.com')

Fare riferimento alla seguente risposta dello stack per una migliore comprensione di Access-Control-Allow-Origin

https://stackoverflow.com/a/10636765/413670


54
È piuttosto pericoloso. Guarda la mia risposta in fondo.
Rob,

3
tnx, ma non dovresti consentire l'accesso a tutte le origini come menzionato da @RobQuist nel suo commento e nella sua risposta ha fornito un approccio migliore
Rafay,

2
Quindi ho trovato questa pagina perché avevo davvero bisogno di 'bypassare' il controllo degli accessi su un server. La soluzione qui non è bypassare nulla, ma semplicemente configurare correttamente il controllo degli accessi sul proprio server. Nel caso in cui qualcuno là fuori abbia effettivamente bisogno di bypassarlo, può usare file_get_contents di PHP ($ remote_url) ;. Esistono ovviamente molti modi per farlo, ma è così che l'ho fatto.
Shawn Whinnery,

1
@ShawnWhinnery questo è fondamentalmente l'atto di "proxy". Buona soluzione se desideri davvero caricare dinamicamente i dati da un altro sito Web di cui non hai il controllo.
Rob,

1
volevo eseguire lo script PHP da dotnet core - ho spostato lo script php nell'altro mio URL ma ho riscontrato un errore di scripting tra siti. aggiunto il codice che hai mostrato all'inizio di PHP e ha funzionato perfettamente. Grazie!
Raddevus,

291

Okay, ma tutti sapete che il * è un carattere jolly e consente lo scripting cross site da ogni dominio?

Vorresti inviare più Access-Control-Allow-Originintestazioni per ogni sito a cui è consentito, ma sfortunatamente non è ufficialmente supportato per inviare più Access-Control-Allow-Originintestazioni o per inserire più origini.

Puoi risolverlo controllando l'origine e rispedendo quello nell'intestazione, se è permesso:

$origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = [
    'http://mysite1.com',
    'https://www.mysite2.com',
    'http://www.mysite2.com',
];

if (in_array($origin, $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $origin);
}

È molto più sicuro. Potresti voler modificare la corrispondenza e cambiarla in una funzione manuale con qualche regex, o qualcosa del genere. Almeno questo restituirà solo 1 intestazione e sarai sicuro che è quello da cui proviene la richiesta. Si prega di notare che tutte le intestazioni HTTP possono essere falsificate, ma questa intestazione è per la protezione del client. Non proteggere i tuoi dati con questi valori. Se vuoi saperne di più, leggi un po 'su CORS e CSRF.

Perché è più sicuro?

Consentendo l'accesso da altre posizioni, il tuo sito attendibile consente l'highjacking della sessione. Vado a fare un piccolo esempio - immagine Facebook consente un'origine jolly - questo significa che puoi creare il tuo sito Web da qualche parte e fargli lanciare chiamate AJAX (o aprire iframe) su Facebook. Questo significa che puoi prendere le informazioni di accesso del facebook di un visitatore del tuo sito web. Ancora peggio - puoi scrivere script di POSTrichieste e pubblicare dati sul facebook di qualcuno - proprio mentre stanno navigando sul tuo sito web.

Fai molta attenzione quando usi le ACAOintestazioni!


12
Penso che sia necessario mettere http: // davanti a ciascun elemento nell'elenco. Almeno l'ho fatto per un sito su cui stavo lavorando.
Blak3,

2
Purtroppo, questo non sembra funzionare. Credo che sia possibile fornire una sola eccezione per chiamata a header ().
lewsid,

5
@Shanimal & lewsid -> Immagino che la virgola separata non funzioni davvero. Riferimento: w3.org/TR/cors
Rob

3
Per trattare con un elenco di domini, qui una risposta rilevante: stackoverflow.com/a/1850482/766177
Valentin Despa

13
È inutile aggiungere 4 intestazioni del genere perché ogni chiamata header()sostituisce l'intestazione precedente dello stesso tipo. Quindi davvero tutto ciò che stai facendo è impostare l'ultima intestazione. La voce manuale indica che è possibile impostare un secondo parametro falseper impedire la sovrascrittura dell'intestazione precedente.
BadHorsie,

31

Attenzione , Chrome (e altri browser) si lamenteranno che sono impostate più intestazioni ACAO se segui alcune delle altre risposte.

L'errore sarà qualcosa di simile XMLHttpRequest cannot load ____. The 'Access-Control-Allow-Origin' header contains multiple values '____, ____, ____', but only one is allowed. Origin '____' is therefore not allowed access.

Prova questo:

$http_origin = $_SERVER['HTTP_ORIGIN'];

$allowed_domains = array(
  'http://domain1.com',
  'http://domain2.com',
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

6
Questa è una soluzione ancora migliore di quella che ho pubblicato.
Rob,

7

Ho risolto questo problema quando ho chiamato un controller MVC3. Ho aggiunto:

Response.AddHeader("Access-Control-Allow-Origin", "*"); 

prima del mio

return Json(model, JsonRequestBehavior.AllowGet);

E mi sono anche $.ajaxlamentato del fatto che non accetta l' intestazione del tipo di contenuto nella mia chiamata ajax, quindi l'ho commentato perché so che il suo JSON è stato passato all'azione.

Spero che aiuti.


2

È una pessima idea da usare *, che ti lascia aperto agli script cross site. Fondamentalmente vuoi il tuo dominio tutto il tempo, nell'ambito delle tue attuali impostazioni SSL e facoltativamente domini aggiuntivi. Si desidera inoltre che vengano inviati tutti come un'unica intestazione. Quanto segue autorizzerà sempre il proprio dominio nello stesso ambito SSL della pagina corrente e può facoltativamente includere anche un numero qualsiasi di domini aggiuntivi. Li invierà tutti come un'intestazione e sovrascriverà quelli precedenti se qualcos'altro li ha già inviati per evitare qualsiasi possibilità che il browser brontoli per l'invio di più intestazioni di controllo di accesso.

class CorsAccessControl
{
    private $allowed = array();

    /**
     * Always adds your own domain with the current ssl settings.
     */
    public function __construct()
    {
        // Add your own domain, with respect to the current SSL settings.
        $this->allowed[] = 'http'
            . ( ( array_key_exists( 'HTTPS', $_SERVER )
                && $_SERVER['HTTPS'] 
                && strtolower( $_SERVER['HTTPS'] ) !== 'off' ) 
                    ? 's' 
                    : null )
            . '://' . $_SERVER['HTTP_HOST'];
    }

    /**
     * Optionally add additional domains. Each is only added one time.
     */
    public function add($domain)
    {
        if ( !in_array( $domain, $this->allowed )
        {
            $this->allowed[] = $domain;
        }
    /**
     * Send 'em all as one header so no browsers grumble about it.
     */
    public function send()
    {
        $domains = implode( ', ', $this->allowed );
        header( 'Access-Control-Allow-Origin: ' . $domains, true ); // We want to send them all as one shot, so replace should be true here.
    }
}

Uso:

$cors = new CorsAccessControl();

// If you are only authorizing your own domain:
$cors->send();

// If you are authorizing multiple domains:
foreach ($domains as $domain)
{
    $cors->add($domain);
}
$cors->send();

Ti viene l'idea.


1

Hai effettivamente provato ad aggiungere l'intestazione Access-Control-Allow-Origin alla risposta inviata dal tuo server? Come Access-Control-Allow-Origin: *?


1
È un'intestazione HTTP che il tuo server invia per informare il browser che va bene rivelare il risultato allo script chiamante nonostante il dominio di origine dello script non corrisponda al dominio del server. Leggi la condivisione delle risorse tra le origini !
Daniel Brockman,
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.