web-dev-qa-db-fra.com

Jeton manquant «access-control-allow-headers» dans l'en-tête CORS «Access-Control-Allow-Headers» du canal de contrôle en amont CORS

J'ai deux projets VS: l'un exposant les contrôleurs MVC5, l'autre étant un client angular. Je veux que le client angular puisse interroger les contrôleurs. I lire de nombreux threads et essayé ce qui suit:

  • J'ai ajouté ceci dans la configuration Web du serveur:

    <system.webServer>
        <httpProtocol>
           <customHeaders>
                <clear />
                <add name="Access-Control-Allow-Origin" value="*" />
            </customHeaders>
        </httpProtocol>
    <system.webServer>
    
  • J'ai créé et utilisé le filtre suivant sur l'action du contrôleur:

    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }
    
  • Dans le client angular, j'ai créé l'intercepteur suivant:

    app.factory("CORSInterceptor", [
        function()
        {
            return {
                request: function(config)
                {
                     config.headers["Access-Control-Allow-Origin"] = "*";
                     config.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";
                     config.headers["Access-Control-Allow-Headers"] = "Content-Type";
                     config.headers["Access-Control-Request-Headers"] = "X-Requested-With, accept, content-type";
                     return config;
                }
         };
    }
    ]);
    
    app.config(["$httpProvider", function ($httpProvider) {
        $httpProvider.interceptors.Push("CORSInterceptor");
    }]);
    

Selon Firebug, cela se traduit par la demande suivante:

OPTIONS //Login/Connect HTTP/1.1
Host: localhost:49815
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:50739
Access-Control-Request-Method: POST
Access-Control-Request-Headers: access-control-allow-headers,access-control-allow-Origin,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

Et la réponse suivante:

HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/10.0
Public: OPTIONS, TRACE, GET, HEAD, POST
X-SourceFiles: =?UTF-8?B?RDpcVEZTXElVV2ViXEdhcE5ldFNlcnZlclxBU1BTZXJ2aWNlc1xMb2dpblxDb25uZWN0?=
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Request-Headers: X-Requested-With, accept, content-type
Date: Tue, 01 Sep 2015 13:05:23 GMT
Content-Length: 0

Et pourtant, Firefox bloque la demande avec le message suivant:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:49815//Login/Connect. (Reason: missing token 'access-control-allow-headers' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
18
Yugo Amaryl

Souvent, les threads que j'ai lus suggéraient plusieurs étapes de configuration inutiles, ce qui créait de la confusion. C'est en fait très simple ...

Dans le but simple d'envoyer une demande intersite, d'un client angular, à un contrôleur ASP:

  • Non angular sont requis.
  • Aucun filtre personnalisé côté serveur n'est requis.
  • La seule modification obligatoire consiste à l'ajouter dans le fichier web.config du serveur

    <system.webServer>
          <httpProtocol>
              <customHeaders>
                  <clear />
                  <add name="Access-Control-Allow-Origin" value="*" />
                  <add name="Access-Control-Allow-Headers" value="Content-Type"/>
              </customHeaders>
         </httpProtocol>
    </system.webServer>
    
30
Yugo Amaryl

Le problème est que certains navigateurs n'autorisent pas encore le * caractère générique pour Access-Control-Allow-Headers. Plus précisément, Firefox 69 et versions antérieures ne le font pas. Voir https://bugzilla.mozilla.org/show_bug.cgi?id=1309358 .

Donc, pour vous assurer d'obtenir le comportement attendu dans tous les navigateurs, le Access-Control-Allow-Headers la valeur que vous renvoyez doit répertorier explicitement tous les noms d'en-tête auxquels vous avez réellement besoin d'accéder à partir de votre code frontal; par exemple, pour le cas de la question: Access-Control-Allow-Headers: Content-Type.

Vous pouvez y arriver sans avoir à coder en dur tous les noms d'en-tête: demandez à votre code côté serveur de prendre la valeur de Access-Control-Request-Headers en-tête de demande envoyé par le navigateur, et en faisant simplement écho dans la valeur de Access-Control-Allow-Headers en-tête de réponse que votre serveur renvoie.

Sinon, utilisez une bibliothèque existante pour activer CORS votre serveur. En écho au Access-Control-Request-Headers valeur d'en-tête de demande dans le Access-Control-Allow-Headers la valeur de l'en-tête de réponse est quelque chose que la plupart des bibliothèques CORS font généralement pour vous.

16
sideshowbarker