Le champ d'en-tête de demande Access-Control-Allow-Headers n'est pas autorisé par lui-même dans la réponse de contrôle en amont


234

J'ai rencontré des problèmes CORS plusieurs fois et je peux généralement les résoudre, mais je veux vraiment comprendre en voyant cela à partir d'un paradigme de pile MEAN.

Avant j'ai simplement ajouté un middleware sur mon serveur express pour attraper ces choses, mais il semble qu'il y ait une sorte de pré-hook qui dérange mes demandes.

Le champ d'en-tête de demande Access-Control-Allow-Headers n'est pas autorisé par Access-Control-Allow-Headers dans la réponse de contrôle en amont

J'ai supposé que je pouvais faire ceci:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","*")
})

ou l'équivalent, mais cela ne semble pas le réparer. J'ai aussi bien sûr essayé

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","Access-Control-Allow-Headers")
})

Toujours pas de chance.

Réponses:


245

Lorsque vous commencez à jouer avec des en-têtes de demande personnalisés, vous obtenez un contrôle en amont CORS. Il s'agit d'une demande qui utilise le OPTIONSverbe HTTP et comprend plusieurs en-têtes, dont l'un Access-Control-Request-Headersrépertorie les en-têtes que le client souhaite inclure dans la demande.

Vous devez répondre à ce contrôle en amont CORS avec les en-têtes CORS appropriés pour que cela fonctionne. Dont l'un est en effet Access-Control-Allow-Headers. Cet en-tête doit contenir les mêmes valeurs que l'en- Access-Control-Request-Headerstête contenait (ou plus).

https://fetch.spec.whatwg.org/#http-cors-protocol explique cette configuration plus en détail.


41
Si vous utilisez Chrome et que vous ne savez pas quels en-têtes sont demandés, utilisez la Developer Console, Network sélectionnez l'appel en cours et vous pouvez voir quels en-têtes sont demandés parAccess-Control-Request-Headers
— Lionel Morrison

5
L'option Developer Console est une bonne option. Vous pouvez également trouver ce dont vous avez besoin en accédant à l'objet de demande sur le serveur et en vidant les valeurs des en-têtes, mais plus précisément la valeur d'en-tête pour "Access-Control-Request-Headers". Ensuite, copiez / collez ceci dans votre response.setHeader ("Access-Control-Allow-Headers", "{coller ici}")
— Software Prophets

7
exemple s'il vous plait!
— Demodave

5
@Demodave un exemple de cela pour moi étaitheader("Access-Control-Allow-Headers: Content-Type")
— Joshua Duxbury

1
@LionelMorrison, utilisation d'outils de développement chromés pour faire correspondre les en-têtes. bien expliqué !!!
— Savina Chandla

119

Voici ce que vous devez ajouter pour que cela fonctionne.

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

Le navigateur envoie une demande de contrôle en amont (avec le type de méthode OPTIONS) pour vérifier si le service hébergé sur le serveur est autorisé à accéder à partir du navigateur sur un domaine différent. En réponse à la demande de contrôle en amont si vous injectez les en-têtes ci-dessus, le navigateur comprend qu'il est correct de faire d'autres appels et j'obtiendrai une réponse valide à mon appel GET / POST réel. vous pouvez restreindre le domaine auquel l'accès est accordé en utilisant Access-Control-Allow-Origin "," localhost, xvz.com "au lieu de *. (* accordera l'accès à tous les domaines)


7
Vous ne pouvez pas combiner *pour ...-Originet truepour ...-Credentials. Il n'échouera pas pour les demandes sans accréditation, mais il ne fonctionnera pas non plus pour les demandes avec accréditation. Voir le lien que j'ai publié dans ma réponse.
— Anne

Merci Manish Arora, j'ai utilisé votre solution dans mon API et cela a fonctionné. HttpContext.Response.Headers.Add ("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT"); HttpContext.Response.Headers.Add ("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Content-Access-Control-Request-Method, Access -Control-Request-Headers "); HttpContext.Response.Headers.Add ("Access-Control-Allow-Origin", " localhost: 4200" );
— Ramakrishnankt

1
Cela veut dire côté serveur que toute cette munging d'en-tête de réponse est nécessaire à cause du "contrôle en amont"? Pourquoi? Surtout pour les en-têtes parfaitement standard? Après avoir utilisé HTTP pendant un certain temps, c'est une nouvelle pour moi que tant de passe-partout sont nécessaires.
— Samantha Atkins

@manish J'avais un ensemble différent de valeurs pour Access-Control-Allow-Headers qui ne fonctionnait pas. Votre ensemble de valeurs l'a fait. Merci d'avoir gagné du temps et de la frustration.
— azakgaim

Existe-t-il un moyen de joker certains en-têtes? Est-ce une mauvaise idée de joker tous les en-têtes? Tels que response.setHeader("Access-Control-Allow-Headers", "*")? Quelle est l'implication de sécurité de faire cela?
— Vadorequest

78

Ce problème résolu avec

 "Origin, X-Requested-With, Content-Type, Accept, Authorization"

Particulier dans mon projet (express.js / nodejs)

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  next();
});

Mettre à jour:

À chaque erreur: Access-Control-Allow-Headers is not allowed by itself in preflight responseerreur, vous pouvez voir ce qui ne va pas avec l' outil de développement Chrome :
entrez la description de l'image ici

l'erreur ci-dessus est manquante, Content-Typealors ajoutez une chaîne Content-TypeàAccess-Control-Allow-Headers


1
Cela ne fonctionnera pas pour tout le monde. La valeur des en-têtes de demande de contrôle d'accès peut varier en fonction de l'environnement. Accédez à l'objet de demande sur le serveur et videz les valeurs de l'en-tête "Access-Control-Request-Headers". Ensuite, copiez / collez ceci dans votre response.setHeader ("Access-Control-Allow-Headers", "{coller ici}")
— Software Prophets

1
Assurez-vous également que vous épelez l'autorisation de la manière américaine et non de la manière britannique. C'est une demi-heure de ma vie que je ne reviendrai pas. Thx USA! [soupir]
— géoidesic

14

La réponse acceptée est correcte, mais j'ai eu du mal à la comprendre. Voici donc un exemple simple pour le clarifier.

Dans ma demande ajax, j'avais un en-tête d'autorisation standard.

$$(document).on('ajaxStart', function(e){
var auth_token = localStorage.getItem(SB_TOKEN_MOBILE);
if( auth_token ) {
    var xhr = e.detail.xhr;

    xhr.setRequestHeader('**Authorization**', 'Bearer ' + auth_token);
}

Ce code produit l'erreur dans la question. Ce que je devais faire sur mon serveur nodejs était d'ajouter une autorisation dans les en-têtes autorisés:

res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,**Authorization**');

6

Pour ajouter aux autres réponses. J'ai eu le même problème et voici le code que j'ai utilisé dans mon serveur express pour autoriser les appels REST:

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'URLs to trust of allow');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  if ('OPTIONS' == req.method) {
  res.sendStatus(200);
  } else {
    next();
  }
});

Ce que ce code fait essentiellement intercepte toutes les demandes et ajoute les en-têtes CORS, puis continue avec mes itinéraires normaux. Lorsqu'il y a une demande OPTIONS, elle ne répond qu'avec les en-têtes CORS.

EDIT: J'utilisais ce correctif pour deux serveurs express nodejs distincts sur la même machine. Finalement, j'ai résolu le problème avec un simple serveur proxy.


Merci! Pouvez-vous expliquer comment vous avez utilisé un simple serveur proxy?
— austin_ce

5

Je viens de rencontrer ce problème moi-même, dans le contexte d'ASP.NET, assurez-vous que votre Web.config ressemble à ceci:

  <system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler"/>-->
  <remove name="TRACEVerbHandler" />
  <!--
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  -->
</handlers>

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

Notez la valeur d'autorisation pour la Access-Control-Allow-Headersclé. Il me manquait la valeur d'autorisation, cette configuration résout mon problème.


5

Très bien, je l'ai utilisé sur un projet Silex

$app->after(function (Request $request, Response $response) {
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set("Access-Control-Allow-Credentials", "true");
        $response->headers->set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        $response->headers->set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    });

2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
— Badacadabra

4

Dans Chrome:

Le champ d'en-tête de demande X-Requested-With n'est pas autorisé par Access-Control-Allow-Headers dans la réponse de contrôle en amont.

Pour moi, cette erreur a été déclenchée par un espace de fin dans l'URL de cet appel.

jQuery.getJSON( url, function( response, status, xhr ) {
   ...
}

3

Juste pour ajouter que vous pouvez également mettre ces en-têtes dans le fichier de configuration Webpack. J'en avais besoin comme dans mon cas car j'utilisais le serveur de développement webpack.

devServer: {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT",
      "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
},


2

J'ai reçu l'erreur indiquée par l'OP en utilisant Django, React et la bibliothèque django-cors-headers. Pour le corriger avec cette pile, procédez comme suit:

Dans settings.py, ajoutez ce qui suit selon la documentation officielle .

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)

2

ce problème se produit lorsque nous créons un en-tête personnalisé pour la demande. Cette demande qui utilise le HTTP OPTIONSet inclut plusieurs en-têtes.

L'en-tête requis pour cette demande est Access-Control-Request-Headers, qui devrait faire partie de l'en-tête de réponse et devrait permettre la demande de toute l'origine. Parfois, il a également besoin Content-Typed'en-tête de réponse. Donc, votre en-tête de réponse devrait être comme ça -

response.header("Access-Control-Allow-Origin", "*"); // allow request from all origin
response.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization");

1

Dans Post API, nous envoyons des données dans le corps de la demande. Donc, si nous envoyons des données en ajoutant un en-tête supplémentaire à un appel API. Ensuite, le premier appel de l'API OPTIONS se produira, puis le post-appel aura lieu. Par conséquent, vous devez d'abord gérer l'appel de l'API OPTION.

Vous pouvez gérer le problème en écrivant un filtre et à l'intérieur que vous devez vérifier l'appel d'API d'appel d'option et retourner un état 200 OK. Voici l'exemple de code:

package com.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Response;

public class CustomFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
        if (httpRequest.getMethod().equalsIgnoreCase("OPTIONS")) {
            response.setStatus(Response.SC_OK);
        }
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
        // TODO
    }

    public void destroy() {
        // Todo
    }

}

1

Si vous essayez d'ajouter un en-tête personnalisé sur les en-têtes de demande, vous devez informer le serveur qu'un en-tête spécifique est autorisé à avoir lieu. L'endroit pour le faire est dans la classe qui filtre les demandes. Dans l'exemple ci-dessous, le nom d'en-tête personnalisé est "type":

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin",  request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, type ");
        response.setHeader("Access-Control-Expose-Headers","Authorization");
    }
}

1

Après avoir passé presque une journée, je viens de découvrir que l'ajout des deux codes ci-dessous a résolu mon problème.

Ajoutez ceci dans le Global.asax

protected void Application_BeginRequest()
{
  if (Request.HttpMethod == "OPTIONS")
  {
    Response.StatusCode = (int)System.Net.HttpStatusCode.OK;             
    Response.End();
  }
}

et dans la configuration Web, ajoutez ce qui suit

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />        
    <add name="Access-Control-Allow-Methods" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
  </customHeaders>
</httpProtocol>

1

Moi aussi, j'ai rencontré le même problème dans Angular 6. J'ai résolu le problème en utilisant le code ci-dessous. Ajoutez le code dans le fichier component.ts.

import { HttpHeaders } from '@angular/common/http';

headers;

constructor() {
    this.headers = new HttpHeaders();
    this.headers.append('Access-Control-Allow-Headers', 'Authorization');
}

getData() {
    this.http.get(url,this.headers). subscribe (res => {
    // your code here...
})}

0

Ce même problème auquel j'étais confronté.

J'ai fait un simple changement.

  <modulename>.config(function($httpProvider){
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
});

0

Le message est clair que «l'autorisation» n'est pas autorisée dans l'API. Définissez
Access-Control-Allow-Headers: "Content-Type, Authorization"


0
const express = require('express')
const cors = require('cors')
const app = express()

app.get('/with-cors', cors(), (req, res, next) => {
  res.json({ msg: 'WHOAH with CORS it works! 🔝 🎉' })
})

Ajouter des cors dans la fonction get est ce qui a fonctionné pour moi

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.