O campo de cabeçalho da solicitação Access-Control-Allow-Headers não é permitido por si só na resposta de comprovação

234

Eu me deparei com problemas do CORS várias vezes e geralmente posso corrigi-lo, mas quero realmente entender vendo isso de um paradigma de pilha do MEAN.

Antes, eu simplesmente adicionava o middleware no meu servidor expresso para capturar essas coisas, mas parece que há algum tipo de pré-gancho que está errando meus pedidos.

Campo de cabeçalho de solicitação Acesso-controle-permitir-cabeçalhos não é permitido por acesso-controle-permitir-cabeçalhos na resposta de comprovação

Eu assumi que eu poderia fazer isso:

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

ou o equivalente, mas isso não parece corrigi-lo. Eu também tentei

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

Ainda sem sorte.

mibbit
fonte

Respostas:

245

Quando você começa a brincar com cabeçalhos de solicitação personalizados, recebe um preflight do CORS. Essa é uma solicitação que usa o OPTIONSverbo HTTP e inclui vários cabeçalhos, um dos quais Access-Control-Request-Headerslistando os cabeçalhos que o cliente deseja incluir na solicitação.

Você precisa responder à verificação prévia do CORS com os cabeçalhos apropriados do CORS para fazer isso funcionar. Um dos quais é de fato Access-Control-Allow-Headers. Esse cabeçalho precisa conter os mesmos valores que o Access-Control-Request-Headerscabeçalho continha (ou mais).

https://fetch.spec.whatwg.org/#http-cors-protocol explica essa configuração com mais detalhes.

Anne
fonte
41
Se você usar o Chrome e você não tem certeza que os cabeçalhos estão sendo solicitados, utilize o console do desenvolvedor, de rede, selecione a chamada que está sendo feito e você pode ver o que os cabeçalhos estão sendo solicitados porAccess-Control-Request-Headers
Lionel Morrison
5
A opção Console do desenvolvedor é boa. Você também pode encontrar o que precisa obtendo acesso ao objeto de solicitação no servidor e despejando os valores dos cabeçalhos, mas especificamente o valor do cabeçalho para "Access-Control-Request-Headers". Em seguida, copie / cole isso em sua response.setHeader ("Access-Control-Allow-Headers", "{paste here}")
Software Profetas
7
exemplo por favor!
Demodave 15/05
5
@Demodave um exemplo disso para mim foiheader("Access-Control-Allow-Headers: Content-Type")
Joshua Duxbury
1
@LionelMorrison, uso de ferramentas de desenvolvimento chrome para combinar cabeçalhos. bem explicado !!!
precisa
119

É isso que você precisa adicionar para fazer funcionar.

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");

O navegador envia uma solicitação de comprovação (com o tipo de método OPTIONS) para verificar se o serviço hospedado no servidor pode ser acessado a partir do navegador em um domínio diferente. Em resposta à solicitação de preflight, se você injetar os cabeçalhos acima, o navegador entende que é possível fazer outras chamadas e receberei uma resposta válida à minha chamada GET / POST real. você pode restringir o domínio ao qual o acesso é concedido usando Access-Control-Allow-Origin "," localhost, xvz.com "em vez de *. (* concederá acesso a todos os domínios)

arora manish
fonte
7
Você não pode combinar *para ...-Origine truepara ...-Credentials. Ele não falhará para solicitações não credenciadas, mas também não funcionará para solicitações credenciadas. Veja o link que eu postei na minha resposta.
Anne
Obrigado Manish Arora, usei sua solução na minha API e funcionou. HttpContext.Response.Headers.Add ("Métodos de permissão de controle de acesso", "GET, HEAD, OPTIONS, POST, PUT"); HttpContext.Response.Headers.Add ("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Tipo de Conteúdo, Tipo de Conteúdo, Access-Control-Request-Method, Access -Control-Request-Headers "); HttpContext.Response.Headers.Add ("Access-Control-Allow-Origin", " localhost: 4200" );
Ramakrishnankt
1
Isso significa que, no lado do servidor, toda essa resposta do cabeçalho de resposta é necessária devido ao "preflight"? Por quê? Especialmente para cabeçalhos perfeitamente padrão? Tendo usado o HTTP por um tempo, é novidade para mim que são necessários tantos clichês.
Samantha Atkins
@manish Eu tinha um conjunto diferente de valores para cabeçalhos de controle de acesso e permissão que não funcionavam. Seu conjunto de valores fez. Obrigado por economizar tempo e frustração.
Azakgaim
Existe uma maneira de curinga alguns cabeçalhos? É uma má idéia curinga todos os cabeçalhos? Tais como response.setHeader("Access-Control-Allow-Headers", "*")? Qual é a implicação de segurança de fazer isso?
Vadorequest 29/09/19
78

Esse problema resolvido com

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

Particular no meu projeto (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();
});

Atualizar:

Sempre erro: Access-Control-Allow-Headers is not allowed by itself in preflight responseerro, você pode ver o que há de errado com a ferramenta de desenvolvedor do chrome :
insira a descrição da imagem aqui

está faltando o erro acima, Content-Typeentão adicione Content-TypeaAccess-Control-Allow-Headers

nguyên
fonte
1
Isso não vai funcionar para todos. O valor para cabeçalhos de solicitação de controle de acesso pode variar com base no ambiente. Obtenha acesso ao objeto de solicitação no servidor e despeje os valores para o cabeçalho "Access-Control-Request-Headers". Em seguida, copie / cole isso em sua response.setHeader ("Access-Control-Allow-Headers", "{paste here}")
Software Profetas
1
Verifique também se você está escrevendo a Autorização da maneira americana, não da maneira britânica. São meia hora da minha vida que não voltarei. Thx USA! [suspiro]
geoidesic 31/01
14

A resposta aceita é boa, mas tive dificuldades para entendê-la. Então, aqui está um exemplo simples para esclarecê-lo.

Na minha solicitação ajax, eu tinha um cabeçalho de autorização padrão.

$$(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);
}

Este código produz o erro na pergunta. O que eu fiz no meu servidor nodejs foi adicionar a autorização nos cabeçalhos permitidos:

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

Para adicionar às outras respostas. Eu tive o mesmo problema e este é o código que usei no meu servidor expresso para permitir chamadas 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();
  }
});

O que esse código basicamente faz é intercepta todos os pedidos e adiciona os cabeçalhos CORS, depois continua com minhas rotas normais. Quando há uma solicitação OPTIONS, ela responde apenas com os cabeçalhos do CORS.

EDIT: eu estava usando essa correção para dois servidores separados nodejs express na mesma máquina. No final, corrigi o problema com um servidor proxy simples.

Luke Kroon
fonte
Obrigado! Você pode explicar como você usou um servidor proxy simples?
austin_ce
5

Acabei de me deparar com esse problema, no contexto do ASP.NET, verifique se o seu Web.config fica assim:

  <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>

Observe o valor de autorização para a Access-Control-Allow-Headerschave. Estava faltando o valor de autorização, essa configuração resolve meu problema.

Josh Siegl
fonte
5

Muito bom eu usei isso em um projeto 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");
    });
Al Kativo
fonte
2
Embora esse código possa responder à pergunta, fornecer um contexto adicional sobre como e / ou por que resolve o problema melhoraria o valor a longo prazo da resposta.
Badacadabra
4

No Chrome:

O campo de cabeçalho de solicitação X-Requested-With não é permitido por Access-Control-Allow-Headers na resposta de comprovação.

Para mim, esse erro foi acionado por um espaço à direita no URL desta chamada.

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

Apenas para adicionar que você também pode colocar esses cabeçalhos no arquivo de configuração do Webpack. Eu precisava deles no meu caso, como eu estava executando o servidor de desenvolvimento 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"
},
Janne
fonte
3

res.setHeader ('Access-Control-Allow-Headers', '*');

Kanomdook
fonte
2

Recebi o erro que o OP declarou usando Django, React e a lib django-cors-headers. Para corrigi-lo com essa pilha, faça o seguinte:

Em settings.py, adicione o abaixo conforme a documentação oficial .

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)
Eric
fonte
2

esse problema ocorre quando criamos um cabeçalho personalizado para request.This solicitação que usa o HTTP OPTIONSe inclui vários cabeçalhos.

O cabeçalho necessário para esta solicitação é Access-Control-Request-Headers, que deve fazer parte do cabeçalho de resposta e deve permitir solicitações de toda a origem. Às vezes, também precisa Content-Typeno cabeçalho da resposta. Portanto, seu cabeçalho de resposta deve ser assim -

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");
Sai prateek
fonte
1

Na chamada Pós-API, estamos enviando dados no corpo da solicitação. Portanto, se enviarmos dados adicionando qualquer cabeçalho extra a uma chamada de API. Em seguida, a primeira chamada da OPTIONS API ocorrerá e a pós-chamada acontecerá. Portanto, você deve lidar com a chamada da OPTION API primeiro.

Você pode solucionar o problema escrevendo um filtro e, no interior, precisará verificar a chamada da API de chamada de opção e retornar um status 200 OK. Abaixo está o código de exemplo:

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
    }

}
bip duplo
fonte
1

Se você estiver tentando adicionar um cabeçalho personalizado nos cabeçalhos de solicitação, informe ao servidor que esse cabeçalho específico pode ocorrer. O local para fazer isso é na classe que filtra os pedidos. No exemplo mostrado abaixo, o nome do cabeçalho personalizado é "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");
    }
}
Kristina Mojanovska
fonte
1

Depois de passar quase um dia, descobri que adicionar os dois códigos abaixo resolveu meu problema.

Adicione isso no Global.asax

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

e na configuração da web adicione o abaixo

<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>
Biruk Belihu
fonte
1

Eu também enfrentei o mesmo problema no Angular 6. Resolvi o problema usando o código abaixo. Adicione o código no arquivo 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...
})}
Karthi The Programmer
fonte
0

Esse mesmo problema que eu estava enfrentando.

Eu fiz uma mudança simples.

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

A mensagem é clara: 'Autorização' não é permitida na API. Definir
acesso-controle-permitir-cabeçalhos: "tipo de conteúdo, autorização"

Rajesh Yadav
fonte
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! 🔝 🎉' })
})

Adicionando cors na função get É o que funcionou para mim

Ayman OUKACHA
fonte