web-dev-qa-db-fra.com

comment contourner Access-Control-Allow-Origin?

Je fais un appel ajax à mon propre serveur sur une plate-forme qu'ils ont définie pour empêcher ces appels ajax (mais j'en ai besoin pour récupérer les données de mon serveur pour afficher les données extraites de la base de données de mon serveur) . Mon script ajax est En travaillant, il peut envoyer les données au script php de mon serveur pour lui permettre de traiter . Cependant, il ne peut pas récupérer les données traitées car elles sont bloquées par "Access-Control-Allow-Origin"

Je n'ai pas accès à la source/au noyau de cette plateforme. Je ne peux donc pas supprimer le script qui m'a été refusé . (P/S, j'ai utilisé la console de Google Chrome et découvert cette erreur)

Le code Ajax comme indiqué ci-dessous:

 $.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);

      } 
  });

ou y a-t-il un code JSON équivalent au script ajax ci-dessus? Je pense que JSON est autorisé.

J'espère que quelqu'un pourra m'aider.

172
ETAN

Mettez ceci au dessus de retrieve.php:

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

Notez que cela désactive efficacement la protection CORS et laisse vos utilisateurs exposés aux attaques. Si vous n'êtes pas absolument certain que vous devez autoriser toutes origines, vous devez le limiter à une origine plus spécifique:

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

D'accord, mais vous savez tous que * est un caractère générique et permet la création de scripts entre sites à partir de tous les domaines?

Vous souhaitez envoyer plusieurs en-têtes Access-Control-Allow-Origin pour chaque site autorisé. Malheureusement, il n'est pas officiellement pris en charge pour envoyer plusieurs en-têtes Access-Control-Allow-Origin ou pour définir plusieurs origines.

Vous pouvez résoudre ce problème en vérifiant l'origine et en renvoyant celui-ci dans l'en-tête, si cela est autorisé:

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

C'est beaucoup plus sûr. Vous voudrez peut-être éditer la correspondance et la changer en une fonction manuelle avec une expression rationnelle, ou quelque chose comme ça. Au moins, cela ne fera que renvoyer 1 en-tête, et vous serez sûr que c'est celui d'où provient la demande. Veuillez noter que tous les en-têtes HTTP peuvent être usurpés, mais que cet en-tête est destiné à la protection du client. Ne protégez pas vos propres données avec ces valeurs. Si vous voulez en savoir plus, lisez un peu sur CORS et CSRF.

Pourquoi est-ce plus sûr?

Autoriser l'accès depuis d'autres emplacements que votre propre site de confiance permet le détournement de session. Je vais vous donner un petit exemple - l'image Facebook autorise une origine générique - cela signifie que vous pouvez créer votre propre site Web quelque part et lui faire déclencher des appels AJAX (ou ouvrir des iframes) sur facebook. Cela signifie que vous pouvez récupérer les informations de connexion du facebook d'un visiteur de votre site Web. Pire encore: vous pouvez créer un script pour les demandes POST et publier des données sur le facebook de quelqu'un, juste pendant qu'il navigue sur votre site Web.

Soyez très prudent lorsque vous utilisez les en-têtes ACAO!

268
Rob Quist

Attention , Chrome (et les autres navigateurs) se plaindront que plusieurs en-têtes ACAO sont définis si vous suivez certaines des réponses.

L'erreur sera quelque chose commeXMLHttpRequest cannot load ____. The 'Access-Control-Allow-Origin' header contains multiple values '____, ____, ____', but only one is allowed. Origin '____' is therefore not allowed access.

Essaye ça:

$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");
}
28
user3638471

J'ai résolu ce problème lors de l'appel d'un contrôleur MVC3 ..__ J'ai ajouté:

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

avant mon

return Json(model, JsonRequestBehavior.AllowGet);

De plus, mon $.ajax se plaignait de ne pas accepter Content-type en-tête dans mon appel ajax.

J'espère que cela pourra aider.

7
Atif Rehman

le mieux serait d’autoriser des domaines uniques, faites attention au http: //:

     header('Access-Control-Allow-Origin: http://www.foo.com', false);
     header('Access-Control-Allow-Origin: http://www.foo2.com', false));
5
Sebastian Viereck

Avez-vous déjà essayé d’ajouter l’en-tête Access-Control-Allow-Origin à la réponse envoyée par votre serveur? Comme, Access-Control-Allow-Origin: *?

2
Daniel Brockman

C'est une très mauvaise idée d'utiliser *, ce qui vous laisse largement ouvert à la création de scripts entre sites. En gros, vous voulez avoir votre propre domaine à tout moment, limité à vos paramètres SSL actuels et éventuellement des domaines supplémentaires. Vous souhaitez également qu’ils soient tous envoyés comme un en-tête. Les éléments suivants autoriseront toujours votre propre domaine dans la même étendue SSL que la page actuelle et peuvent éventuellement inclure un nombre quelconque de domaines supplémentaires. Il les enverra tous comme un seul en-tête et écrasera le (s) précédent (s) si quelque chose d’autre leur a déjà été envoyé pour éviter que le navigateur ne se plaint du fait que plusieurs en-têtes de contrôle d’accès soient envoyés.

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.
    }
}

Usage:

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

Vous avez eu l'idée.

0
mopsyd