J'ai rencontré plusieurs fois les problèmes de la SCRO et je peux généralement y remédier, mais je veux vraiment comprendre en le voyant à partir d'un paradigme de pile MEAN.
Auparavant, j’avais simplement ajouté un middleware dans mon serveur express pour récupérer ces informations, mais il semble qu’il existe une sorte de pré-hook qui écarte mes requêtes.
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 résoudre le problème. 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.
Lorsque vous commencez à vous amuser avec des en-têtes de requête personnalisés, vous obtenez un contrôle en amont CORS. Il s'agit d'une demande qui utilise le verbe HTTP OPTIONS
et comprend plusieurs en-têtes, dont l'un est Access-Control-Request-Headers
, qui répertorie les en-têtes que le client souhaite inclure dans la demande.
Vous devez répondre à ce contrôle en amont avec les en-têtes CORS appropriés pour que cela fonctionne. L'un d'eux est en effet Access-Control-Allow-Headers
. Cet en-tête doit contenir les mêmes valeurs que l'en-tête Access-Control-Request-Headers
contenu (ou plus).
https://fetch.spec.whatwg.org/#http-cors-protocol explique cette configuration plus en détail.
C’est 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 l'accès au service hébergé sur le serveur est autorisé à partir du navigateur sur un autre domaine. 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 d'effectuer d'autres appels et que je recevrai une réponse valide à mon appel GET/POST actuel. vous pouvez contraindre 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).
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:
Every time error: Access-Control-Allow-Headers is not allowed by itself in preflight response
error vous pouvez voir ce qui ne va pas avec outil de développement chrome :
l'erreur ci-dessus est manquante Content-Type
donc ajoutez la chaîne Content-Type
à Access-Control-Allow-Headers
La réponse acceptée est ok, 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**');
Pour ajouter aux autres réponses. J'ai eu le même problème et c'est 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();
}
});
En gros, ce code intercepte toutes les demandes et ajoute les en-têtes CORS, puis continue avec mes routes normales. 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 nodejs express distincts sur le même ordinateur. En fin de compte, j'ai résolu le problème avec un simple serveur proxy.
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 clé Access-Control-Allow-Headers
. Il me manquait la valeur d'autorisation, cette configuration résout mon problème.
Très bon 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");
});
En 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 ) {
...
}
Juste pour ajouter que vous pouvez également mettre ces en-têtes dans le fichier de configuration Webpack. J'avais besoin d'eux comme dans mon cas car j'utilisais Webpack dev server.
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"
},
ce problème se produit lorsque nous créons un en-tête personnalisé pour request.Cette demande qui utilise le HTTP OPTIONS
et inclut plusieurs en-têtes.
L'en-tête requis pour cette demande estAccess-Control-Request-Headers
, qui devrait faire partie de l'en-tête de la réponse et devrait autoriser la demande de toute l'origine. Parfois, il faut aussi Content-Type
dans l'en-tête de la 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");
res.setHeader ('Access-Control-Allow-Headers', '*');
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>
J'ai reçu l'erreur mentionnée par l'OP avec Django, React et les librairies Django-cors-headers. Pour le réparer avec cette pile, procédez comme suit:
Dans settings.py, ajoutez ce qui suit sous la documentation officielle .
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)
Dans l'appel post API, nous envoyons des données dans le corps de la demande. Donc, si nous allons envoyer des données en ajoutant un en-tête supplémentaire à un appel API. Ensuite, le premier appel API OPTIONS aura lieu, puis un appel ultérieur. Par conséquent, vous devez d'abord gérer l'appel API OPTION.
Vous pouvez gérer le problème en écrivant un filtre et dans lequel vous devez vérifier l'appel de l'API d'appel d'option et renvoyer l'é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
}
}
Moi aussi, j'ai fait face au même problème dans Angular 6. J'ai résolu le problème en utilisant le code ci-dessous.
Add the code in component.ts file.
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...
})
}
Ce même problème auquel je faisais face.
J'ai fait un changement simple.
<modulename>.config(function($httpProvider){
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Le message indique clairement que l'autorisation n'est pas autorisée dans l'API. Ensemble
Access-Control-Allow-Headers: "Type de contenu, autorisation"