La réponse à la demande de contrôle en amont ne passe pas la vérification du contrôle d'accès

458

Je reçois cette erreur en utilisant ngResource pour appeler une API REST sur Amazon Web Services:

XMLHttpRequest ne peut pas charger http://server.apiurl.com:8000/s/login?login=facebook . La réponse à la demande de contrôle en amont ne passe pas la vérification du contrôle d'accès: aucun en-tête «Access-Control-Allow-Origin» n'est présent sur la ressource demandée. L'origine ' http: // localhost ' n'est donc pas autorisée à y accéder. Erreur 405

Un service:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

Manette:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

J'utilise Chrome et je ne sais pas quoi faire d'autre pour résoudre ce problème. J'ai même configuré le serveur pour accepter les en-têtes d'origine localhost.

Andre Mendes
la source
confus: avez-vous "configuré le serveur" ou est-ce "une api de repos sur le service web amazon"?
dandavis
3
Vous n'avez clairement pas fait assez pour activer CORS côté serveur. Poster un échantillon des en
charlietfl
4
De toute façon, vos votes négatifs sont faux. Il héberge ses fichiers sur sa machine locale. Peu importe le type de conf qu'il fait à l'arrière. Angular ne permettra pas ce pré vol.
E. Maggini
3
Thx pour les commentaires, cela a fonctionné lorsque j'ai mis le navigateur en veille
Andre Mendes le
1
@Andre Mais désactiver la sécurité n'est qu'une solution de contournement laide où vous compromettez la sécurité, ne résout pas votre problème ...
shivi

Réponses:

241

Vous rencontrez des problèmes CORS.

Il existe plusieurs façons de résoudre ce problème.

  1. Désactivez CORS. Par exemple: comment désactiver les cors en chrome
  2. Utilisez un plugin pour votre navigateur
  3. Utilisez un proxy tel que nginx. exemple de configuration
  4. Suivez la configuration nécessaire pour votre serveur. C'est plus un facteur du serveur Web que vous avez chargé sur votre instance EC2 (en supposant que c'est ce que vous entendez par «service Web Amazon»). Pour votre serveur spécifique, vous pouvez vous référer au site Web d'activation de CORS.

Plus verbeusement, vous essayez d'accéder à api.serverurl.com depuis localhost. Il s'agit de la définition exacte de la demande interdomaine.

En le désactivant juste pour faire votre travail (OK, mettez une mauvaise sécurité pour vous si vous visitez d'autres sites et lancez la boîte en bas de la route), vous pouvez utiliser un proxy qui fait que votre navigateur pense que toutes les demandes proviennent d'un hôte local lorsque vous avez vraiment un serveur local qui appelle ensuite le serveur distant.

donc api.serverurl.com peut devenir localhost: 8000 / api et votre nginx local ou un autre proxy enverra à la bonne destination.


Maintenant, à la demande générale, 100% d'informations CORS en plus .... même bon goût!


Et pour les downvoters .... contourner CORS est exactement ce qui est montré pour ceux qui apprennent simplement le frontal. https://codecraft.tv/courses/angular/http/http-with-promises/

E. Maggini
la source
776
laissé de côté la mise en œuvre correcte de
CORS
40
Il est facile de voter contre. Moins facile de prendre le risque toi-même mon ami. Et tout cela fonctionne exactement dans un environnement de développement.
E. Maggini
3
Cela a vraiment fonctionné. J'ai ajouté le drapeau pour désactiver la sécurité Web. Pour le développement, c'est bien.
Andre Mendes
15
@charlietfl Comment?
GreenAsJade
3
Merci d'avoir sauvé ma journée. Première option utilisée uniquement: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. De: stackoverflow.com/questions/3102819/…
Harsimer
169

Mon "API Server" est une application PHP, donc pour résoudre ce problème, j'ai trouvé la solution ci-dessous pour fonctionner:

Placez les lignes dans index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
Slipstream
la source
3
Je suis d'accord, c'est mieux que la réponse acceptée bien que soyez prudent lors de la copie de ces lignes, assurez-vous de modifier les méthodes et l'origine.
Amir Savand du
11
Où le mettre dans un projet Angular 6?
whatthefish
@CodyBugstein et ce que les poissons mettent avant toute sortie
Garet Claborn
Mon application client a cessé de fonctionner lorsque j'ai ajouté un en-tête qui n'est requis que par certains serveurs. Si la demande comprend des en-têtes personnalisés, ils devront être répertoriés dans Access-Control-Allow-Headers.
z0r
47

Dans l'API Web AspNetCore, ce problème a été résolu en ajoutant "Microsoft.AspNetCore.Cors" (ver 1.1.1) et en ajoutant les modifications ci-dessous sur Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

et

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

et mettre [EnableCors("AllowAllHeaders")]le contrôleur.

Rajkumar Peter
la source
18
C'est une bonne réponse si vous souhaitez intégrer des vulnérabilités de script intersite! Veuillez ne jamais faire ça! Spécifiez vos domaines auxquels vous pouvez accéder pour éviter les problèmes de sécurité. CORS est là pour une raison.
paqogomez
2
Juste pour être plus clair @paqogomez, dans votre méthode ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); et dans votre méthode Configure: app.UseCors ("AllowSpecificOrigin");
Francisco Tena du
28

Il y a quelques mises en garde en ce qui concerne CORS. Tout d'abord, il n'autorise pas les caractères génériques, *mais ne me tenez pas sur celui-ci, je l'ai lu quelque part et je ne trouve pas l'article maintenant.

Si vous faites des demandes à partir d'un autre domaine, vous devez ajouter les en-têtes d'origine autorisés.

 Access-Control-Allow-Origin: www.other.com 

Si vous faites des demandes qui affectent les ressources du serveur comme POST / PUT / PATCH, et si le type MIME est différent de celui qui suit application/x-www-form-urlencoded, multipart/form-dataou text/plainle navigateur fera automatiquement un OPTIONS prévol demande de vérifier avec le serveur si elle lui permettrait .

Donc, votre API / serveur doit gérer ces demandes OPTIONS en conséquence, vous devez répondre avec le access control headerscode d'état de réponse http approprié 200.

Les en-têtes devraient être quelque chose comme ça, ajustez-les en fonction de vos besoins:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

L'en-tête max-age est important, dans mon cas, cela ne fonctionnerait pas sans lui, je suppose que le navigateur a besoin des informations pour combien de temps les "droits d'accès" sont valides.

De plus, si vous faites par exemple une POSTdemande avec du application/jsonmime d'un autre domaine, vous devez également ajouter l'en-tête origin origin autoriser mentionné, ainsi cela ressemblerait à ceci:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Lorsque le pré-vol réussit et obtient toutes les informations nécessaires, votre demande réelle sera effectuée.

De manière générale, quels que soient les en- Access-Controltêtes demandés dans la demande initiale ou avant le vol, ils doivent être indiqués dans la réponse pour que cela fonctionne.

Il y a un bon exemple dans les documents MDN ici sur ce lien , et vous devriez également consulter cet article SO

Sasa Blagojevic
la source
1
Voici l'article de Mozilla expliquant comment vous ne pouvez pas utiliser de caractères génériques pour l'origine des cors: Lien Donc, apparemment, cela ne s'applique que lorsque vous utilisez des informations d'identification (si je comprends bien)
Helzgate
J'utilise un caractère générique et je soumets un jeton au porteur pour autoriser la demande et cela fonctionne bien, donc je ne sais pas à quoi le lien que j'ai fourni ci-dessus fait référence en ce qui concerne les informations d'identification. Mon problème était que lors de l'intégration de ma stratégie CORS dans .Net Core, je n'ai pas ajouté .AllowCredentials(). Après avoir ajouté .AllowCredentials()tout a fonctionné.
Helzgate
15

JavaScript XMLHttpRequest et Fetch suivent la même politique d'origine. Ainsi, une application Web utilisant XMLHttpRequest ou Fetch ne pouvait effectuer des requêtes HTTP que vers son propre domaine.

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Vous devez envoyer l'en - tête HTTP Access-Control-Allow-Origin: * depuis votre serveur.

Si vous utilisez Apache comme serveur HTTP, vous pouvez l'ajouter à votre fichier de configuration Apache comme ceci:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers est activé par défaut dans Apache, cependant, vous pouvez vous assurer qu'il est activé en exécutant:

 a2enmod headers
Tadej
la source
Où puis-je trouver mon fichier de configuration Apache?
Shubham Arya
@ShubhamArya sur Linux Debian l'emplacement par défaut est:/etc/apache2/apache2.conf
Tadej
où puis-je le trouver dans les fenêtres?
Shubham Arya
10

Si vous écrivez une extension chrome

Vous devez ajouter manifest.jsonles autorisations pour votre ou vos domaines.

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
Liberté
la source
1
Vérifiez également si vous avez le préfixe www
Vlas Bashynskyi
8

Si vous utilisez le serveur IIS par hasard. vous pouvez définir des en-têtes ci-dessous dans l'option En-têtes de requête HTTP.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

avec tout cela, obtenez etc., fonctionnera bien.

Sunil Kumar
la source
5

En PHP, vous pouvez ajouter les en-têtes:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...
atiruz
la source
merci, ça a marché pour moi! dans les tests et l'environnement de production. Même en utilisant https: //
Jose Seie
1
@atiruz Merci pour la solution. Cela fonctionne quand j'ai ajouté la ligneheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD
5

Pour résoudre les problèmes de demandes d'origine croisée dans une application Node JS:

npm i cors

Et ajoutez simplement les lignes ci-dessous au app.js

let cors = require('cors')
app.use(cors())
Rohit Parte
la source
3
cela ne fonctionne que dans les applications express js, pas toutes les applications de noeud
DrCord
3

Dans mon fichier de configuration Apache VirtualHost, j'ai ajouté les lignes suivantes:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
hugsbrugs
la source
3

Pour ceux qui utilisent Lambda Integrated Proxy avec API Gateway . Vous devez configurer votre fonction lambda comme si vous lui soumettiez directement vos demandes, ce qui signifie que la fonction doit configurer correctement les en-têtes de réponse. (Si vous utilisez des fonctions lambda personnalisées, cela sera géré par la passerelle API.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
la source
1
Je veux également carillon et mentionner un gros problème, je ne pense pas que les documents AWS. Supposons que vous utilisez une passerelle API pour proxy votre fonction lambda et que vous utilisez une API dans cette fonction lambda. Si cette API renvoie un code de réussite non 200 et que vous n'avez pas ajouté le code de réussite non 200 dans la réponse de la méthode dans la passerelle API, vous recevrez une erreur et vous ne verrez pas votre réponse réussie . Exemples: Sendgrid et Twilio ont des codes de réussite différents de 200.
Stephen Tetreault
3

Je pense que désactiver CORS à partir de Chrome n'est pas un bon moyen , car si vous l'utilisez dans ionic, certainement dans Mobile Build, le problème se posera à nouveau.

Il vaut donc mieux fixer dans votre backend.

Tout d'abord dans l'en-tête, vous devez définir

  • en-tête ('Access-Control-Allow-Origin: *');
  • header ('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

Et si l'API se comporte comme GET et POST, définissez également votre en-tête-

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header ("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}")); sortie (0); }

Shubham Pandey
la source
3

Une cause très courante de cette erreur pourrait être que l'API hôte avait mappé la demande à une méthode http (par exemple PUT) et que le client API appelle l'API à l'aide d'une méthode http différente (par exemple POST ou GET)

Christian Nwafor
la source
PUT
J'implémentais CORS
3

Notre équipe le voit de temps en temps en utilisant Vue, axios et un C # WebApi. L'ajout d'un attribut d'itinéraire sur le point de terminaison que vous essayez de résoudre le corrige pour nous.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
la source
Nous ne savons pas vraiment pourquoi. Lol. Si quelqu'un me le fait savoir!
w00ngy
1

J'ai rencontré ce problème lorsque le serveur DNS a été défini sur 8.8.8.8 (google's). En fait, le problème était dans le routeur, mon application a essayé de se connecter au serveur via Google, pas localement (pour mon cas particulier). J'ai supprimé 8.8.8.8 et cela a résolu le problème. Je sais que ce problème est résolu par les paramètres CORS, mais peut-être que quelqu'un aura le même problème que moi

Kirill Gusyatin
la source
1

J'utilise AWS sdk pour les téléchargements, après avoir passé du temps à chercher en ligne, je suis tombé sur ce fil. grâce à @lsimoneau 45581857, il se passe exactement la même chose. J'ai simplement pointé ma demande d'URL vers la région sur mon compartiment en attachant l'option région et cela a fonctionné.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
la source
0

Les distributions autonomes de GeoServer incluent le serveur d'applications Jetty. Activez le partage de ressources d'origine croisée (CORS) pour permettre aux applications JavaScript en dehors de votre propre domaine d'utiliser GeoServer.

Décommentez les éléments suivants <filter>et à <filter-mapping>partir de webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Yassine Ech-Charafi
la source
Cela n'a pas ajouté d'antyhing à l'en-tête de la réponse, donc cela n'a pas fonctionné
JollyRoger
1
n'utilise pas GeoServer, mais ce clip m'a aidé à connaître les paramètres que je devais utiliser sur l'application recevant l'appel.
Matt Felzani
0

Il est facile de résoudre ce problème simplement en quelques étapes, sans vous soucier de rien. Veuillez suivre les étapes pour le résoudre.

  1. ouvert ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. allez à l'installation et copiez la commande npm install cors à installer via le terminal de noeud
  3. allez à Utilisation simple (Activer toutes les demandes CORS) en faisant défiler.puis copiez et collez la déclartion complète dans votre projet et exécutez-la ... cela fonctionnera à coup sûr .. copiez le code de commentaire et collez-le dans ur app.js ou tout autre projetez et essayez .. cela fonctionnera. cela débloquera chaque partage de ressources d'origine croisée ... afin que nous puissions basculer entre les services pour votre usage
Rahul sah
la source
1
var express = require ('express') var cors = require ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', function (req, res, suivant) {res.json ({msg: 'Ceci est compatible CORS pour toutes les origines!'})}) app.listen (80, function () {console.log ('Serveur Web compatible CORS écoutant sur le port 80') )})
Rahul sah
-1

Quelque chose qui est très facile à manquer ...

Dans l'explorateur de solutions, cliquez avec le bouton droit sur api-project. Dans la fenêtre des propriétés, réglez «Authentification anonyme» sur Activé !!!

Nous s
la source
-8

Désactivez la sécurité de chrome. Créez un raccourci de chrome, faites un clic droit -> propriétés -> cible, collez ce "C: \ Program Files (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user -data-dir = "c: / chromedev"

Nithin
la source