L'origine n'est pas autorisée par Access-Control-Allow-Origin

337

Je crée un Ajax.requestserveur PHP distant dans une application Sencha Touch 2 (enveloppée dans PhoneGap ).

La réponse du serveur est la suivante:

XMLHttpRequest ne peut pas charger http://nqatalog.negroesquisso.pt/login.php . L'origine http://localhost:8888n'est pas autorisée par Access-Control-Allow-Origin.

Comment puis-je résoudre ce problème?

Ricardo
la source
19
lors de l'utilisation de jQuery, le réglage dataType: 'jsonp',fait l'affaire
amit
11
d'ailleurs ce n'est pas la réponse du serveur. Pour être précis, cette erreur est émise côté client.
matteo
2
L'astuce jsonp ne fonctionne probablement plus, fyi: stackoverflow.com/questions/12216208/…
tiré
7
Remarque, puisque je viens de perdre une demi-journée à chasser ce bogue - Si le script côté serveur échoue avec une erreur de serveur interne, le navigateur peut l'interpréter comme si la demande n'était pas autorisée en raison de Access-Control-Allow-Originet signaler cela comme une erreur.
troelskn
1
@troelskn Vous venez de me sauver la vie. Je cherchais une erreur CORS depuis 3 jours, et c'était simplement un petit problème de configuration de Spring provoquant un 500, que j'ai résolu en 5 minutes une fois que j'ai lu votre commentaire et que je l'ai effectivement cherché. Je vous remercie!
Alexis Dufrenoy

Réponses:

378

J'ai écrit un article sur cette question il y a quelque temps, Cross Domain AJAX .

La façon la plus simple de gérer cela si vous avez le contrôle du serveur répondant est d'ajouter un en-tête de réponse pour:

Access-Control-Allow-Origin: *

Cela permettra Ajax inter-domaine . En PHP, vous voudrez modifier la réponse comme ceci:

<?php header('Access-Control-Allow-Origin: *'); ?>

Vous pouvez simplement mettre le Header set Access-Control-Allow-Origin *paramètre dans la configuration Apache ou le fichier htaccess.

Il convient de noter que cela désactive efficacement la protection CORS, ce qui expose très probablement vos utilisateurs aux attaques . Si vous ne savez pas que vous devez spécifiquement utiliser un caractère générique, vous ne devez pas l'utiliser, et vous devez plutôt mettre votre domaine spécifique en liste blanche:

<?php header('Access-Control-Allow-Origin: http://example.com') ?>
Matt Mombrea
la source
4
Je vais contacter mon fournisseur de serveur. Merci
Ricardo
8
Y a-t-il des problèmes de sécurité à ce sujet? Cette réponse , par exemple, indique que "JavaScript est limité par la" même politique d'origine "pour des raisons de sécurité. Par exemple, un script malveillant ne peut pas contacter un serveur distant et envoyer des données sensibles depuis votre site."
JohnK
4
Génial, je viens de le mettre dans mon fichier serveur node.js: response.writeHead (200, {'Content-Type': contentType, 'Access-Control-Allow-Origin': '*'}); Et ça a marché. Merci!
vbullinger
25
JohnK, oui, le caractère générique va permettre à n'importe quel domaine d'envoyer des demandes à votre hôte. Je recommande de remplacer l'astérisque par un domaine spécifique sur lequel vous exécuterez des scripts.
Nick
7
Il est intéressant de penser que le caractère générique ne devrait même pas être suggéré @jfrej. Tout dépend de votre objectif. Par exemple, la raison pour laquelle nous avons utilisé le caractère générique (et publié cette réponse) était parce que nous construisions un widget intégré pour n'importe quel site à utiliser.
Matt Mombrea
63

Si vous n'avez le contrôle du serveur, vous pouvez simplement ajouter cet argument à votre lanceur d'applications Chrome: .--disable-web-security

Notez que je ne l'utiliserais pas pour une "navigation sur le Web" normale. Pour référence, consultez cet article: désactiver la même politique d'origine dans Chrome .

Celui que vous utilisez Phonegap pour réellement créer l'application et la charger sur l'appareil, ce ne sera pas un problème.

Travis Webb
la source
Merci. Mais mon application fonctionne sur des appareils mobiles, je ne peux pas transmettre d'arguments à mon wrapper de vue Web.
Ricardo
Ne testez-vous pas d'abord votre application dans un navigateur? Comment déboguez-vous?
Travis Webb
Oui, je débogue dans un navigateur Chrome, mais l'application ne fonctionnera pas sur Chrome. Ce sera sur phonegap webview witch je ne peux pas contrôler.
Ricardo
4
lisez la réponse: vous pouvez simplement ajouter cet argument à votre lanceur Chrome . Il n'y a aucun paramètre pour cela dans Chrome
Travis Webb
2
Bien sûr, ce n'est pas sûr. Le PO demande un moyen de contourner les mesures de sécurité.
Travis Webb
42

Si vous utilisez Apache, ajoutez simplement:

<ifModule mod_headers.c>
    Header set Access-Control-Allow-Origin: *
</ifModule>

dans votre configuration. Ainsi, toutes les réponses de votre serveur Web seront accessibles à partir de tout autre site Internet. Si vous avez l'intention d'autoriser uniquement l'utilisation des services de votre hôte par un serveur spécifique, vous pouvez remplacer le *par l'URL du serveur d'origine:

Header set Access-Control-Allow-Origin: http://my.origin.host
Reza S
la source
3
Et n'oubliez pas de charger le module: en
Walery Strauch
comment charger le module: en-têtes a2enmod?
Ayesha
18

Si vous avez une application ASP.NET / ASP.NET MVC , vous pouvez inclure cet en-tête via le fichier Web.config:

<system.webServer>
  ...

    <httpProtocol>
        <customHeaders>
            <!-- Enable Cross Domain AJAX calls -->
            <remove name="Access-Control-Allow-Origin" />
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>
C. Augusto Proiete
la source
2
.NET MVC People, REGARDEZ ici! Je vais en fait taper une solution et pointer cette réponse sur mon blog afin que les gens puissent la trouver plus facilement. Rien de pire que d'essayer de dépasser un obstacle .NET / MVC et de ne trouver que des solutions PHP / jQuery. Merci @ Caio-Proiete
ottoflux
1
Pourquoi cela ne fonctionne-t-il pas pour moi? J'utilise Chrome et j'essaie d'accéder à la page des finances de Yahoo depuis mon hôte local.
newman
1
merci ça a marché pour moi. J'ai ajouté dans le projet de code côté serveur (web.config).
ethem
15

Ce fut la première question / réponse qui est apparue pour moi lorsque j'essayais de résoudre le même problème en utilisant ASP.NET MVC comme source de mes données. Je me rends compte que cela ne résout pas la question PHP , mais il est suffisamment lié pour être utile.

J'utilise ASP.NET MVC. Le billet de blog de Greg Brant a fonctionné pour moi. En fin de compte, vous créez un attribut, [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]que vous pouvez ajouter aux actions du contrôleur.

Par exemple:

public class HttpHeaderAttribute : ActionFilterAttribute
{
    public string Name { get; set; }
    public string Value { get; set; }
    public HttpHeaderAttribute(string name, string value)
    {
        Name = name;
        Value = value;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.AppendHeader(Name, Value);
        base.OnResultExecuted(filterContext);
    }
}

Et puis l'utiliser avec:

[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
    return Json( "Some public result" );
}
badMonkey
la source
1
WebApi 2 a intégré cela maintenant. asp.net/web-api/overview/security/…
Matt Frear
10

Comme Matt Mombrea est correct pour le côté serveur, vous pourriez rencontrer un autre problème qui est le rejet de la liste blanche.

Vous devez configurer votre phonegap.plist. (J'utilise une ancienne version de phonegap)

Pour cordova, il pourrait y avoir quelques changements dans le nom et le répertoire. Mais les étapes doivent être essentiellement les mêmes.

Sélectionnez d'abord Fichiers de support> PhoneGap.plist

entrez la description de l'image ici

puis sous "ExternalHosts"

Ajoutez une entrée, avec une valeur de peut-être " http://nqatalog.negroesquisso.pt " J'utilise * à des fins de débogage uniquement.

entrez la description de l'image ici

steve0hh
la source
8

Cela peut être pratique pour quiconque a besoin d'une exception pour les versions "www" et "non www" d'un référent:

 $referrer = $_SERVER['HTTP_REFERER'];
 $parts = parse_url($referrer);
 $domain = $parts['host'];

 if($domain == 'google.com')
 {
         header('Access-Control-Allow-Origin: http://google.com');
 }
 else if($domain == 'www.google.com')
 {
         header('Access-Control-Allow-Origin: http://www.google.com');
 }
lewsid
la source
Me dirigea dans la bonne direction pour résoudre l'erreur ACAO avec l'azur. Alors que j'avais ajouté le nom d'hôte autorisé de googledrive. L'URL utilisée doit être googledrive PAS googledrive
Kildareflare
7

Je vais vous donner une solution simple pour celle-ci. Dans mon cas, je n'ai pas accès à un serveur. Dans ce cas, vous pouvez modifier la politique de sécurité de votre navigateur Google Chrome pour autoriser Access-Control-Allow-Origin. C'est très simple:

  1. Créer un raccourci de navigateur Chrome
  2. Cliquez avec le bouton droit sur l'icône de raccourci -> Propriétés -> Raccourci -> Cible

Coller simplement "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.

L'emplacement peut différer. Ouvrez maintenant Chrome en cliquant sur ce raccourci.

Dibish
la source
7

J'ai rencontré cela plusieurs fois en travaillant avec diverses API. Souvent, une solution rapide consiste à ajouter "& callback =?" à la fin d'une chaîne. Parfois l'esperluette doit être un code de caractère, et parfois un "?": "? Callback =?" (voir Utilisation de l'API Forecast.io avec jQuery )

Francis Baptiste
la source
6

Si vous écrivez une extension Chrome et obtenir cette erreur, alors assurez - vous que vous avez ajouté l'URL de base de l'API à votre manifest.jsonde bloc d'autorisations , par exemple:

"permissions": [
    "https://itunes.apple.com/"
]
itzg
la source
6

Cela est dû à la politique de même origine . Voir plus sur Mozilla Developer Network ou Wikipedia .

Fondamentalement, dans votre exemple, vous devez http://nqatalog.negroesquisso.pt/login.phpuniquement charger la page à partir de nqatalog.negroesquisso.pt, pas localhost.

antyrat
la source
1
Mais j'ai besoin de charger le webservice à partir d'un appareil mobile, je contournerais cela?
Ricardo
Eh bien, vous devez apporter des modifications côté serveur ou utiliser JSONP en.wikipedia.org/wiki/JSONP
antyrat
6

si vous êtes sous apache, ajoutez simplement un fichier .htaccess à votre répertoire avec ce contenu:

Header set Access-Control-Allow-Origin: *

Header set Access-Control-Allow-Headers: content-type

Header set Access-Control-Allow-Methods: *
Vero O
la source
5

Dans Ruby on Rails , vous pouvez faire dans un contrôleur:

headers['Access-Control-Allow-Origin'] = '*'
fuzzyalej
la source
dans quel contrôleur mettez-vous cela si c'est un appel ajax? Puis-je voir plus de contexte de code?
rigdonmr
5

Vous pouvez le faire fonctionner sans modifier le serveur en créant le navigateur en incluant l'en-tête Access-Control-Allow-Origin: *dans les réponses des OPTIONS HTTP.

Dans Chrome, utilisez cette extension . Si vous êtes sur Mozilla, vérifiez cette réponse .

forzagreen
la source
5

Si vous obtenez ceci dans Angular.js, alors assurez-vous d'échapper votre numéro de port comme ceci:

var Project = $resource(
    'http://localhost\\:5648/api/...', {'a':'b'}, {
        update: { method: 'PUT' }
    }
);

Voir ici pour plus d'informations à ce sujet.

Marius
la source
4

Nous avons également le même problème avec l'application phonegap testée en chrome. Une machine Windows que nous utilisons tous les jours sous le fichier de commandes avant d'ouvrir Chrome. Rappelez-vous qu'avant d'exécuter cela, vous devez nettoyer toutes les instances de chrome du gestionnaire de tâches ou vous pouvez sélectionner chrome pour ne pas l'exécuter en arrière-plan.

LOT: (utilisez cmd)

cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security
abksharma
la source
1

Dans Ruby Sinatra

response['Access-Control-Allow-Origin'] = '*' 

pour tout le monde ou

response['Access-Control-Allow-Origin'] = 'http://yourdomain.name' 
Mikhail Chuprynski
la source
0

Lorsque vous recevez la demande, vous pouvez

var origin = (req.headers.origin || "*");

que lorsque vous devez répondre, allez avec quelque chose comme ça:

res.writeHead(
    206,
    {
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Origin': origin,
    }
);
Alessandro Annini
la source