Bidang tajuk permintaan Access-Control-Allow-Headers tidak diizinkan dengan sendirinya dalam respons preflight


234

Saya telah menemukan masalah CORS beberapa kali dan biasanya dapat memperbaikinya tetapi saya ingin benar-benar mengerti dengan melihat ini dari paradigma tumpukan MEAN.

Sebelumnya saya hanya menambahkan middleware di server ekspres saya untuk menangkap hal-hal ini, tetapi sepertinya ada beberapa jenis pre-hook yang tidak memenuhi permintaan saya.

Bidang header permintaan Access-Control-Allow-Headers tidak diizinkan oleh Access-Control-Allow-Header dalam respons preflight

Saya berasumsi bahwa saya bisa melakukan ini:

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

atau setara tetapi ini tampaknya tidak memperbaikinya. Saya juga tentu saja mencoba

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

Masih belum berhasil.

Jawaban:


245

Saat Anda mulai bermain-main dengan header permintaan khusus, Anda akan mendapatkan preflight CORS. Ini adalah permintaan yang menggunakan OPTIONSkata kerja HTTP dan menyertakan beberapa tajuk, yang salah satunya adalah Access-Control-Request-Headersdaftar tajuk yang ingin dimasukkan klien dalam permintaan.

Anda harus membalas preflight CORS dengan header CORS yang sesuai untuk membuat pekerjaan ini. Salah satunya memang Access-Control-Allow-Headers. Header itu harus berisi nilai yang sama dengan Access-Control-Request-Headersheader yang ada (atau lebih).

https://fetch.spec.whatwg.org/#http-cors-protocol menjelaskan pengaturan ini secara lebih rinci.


41
Jika Anda menggunakan Chrome dan tidak yakin tajuk apa yang diminta, gunakan Konsol Pengembang, Jaringan pilih panggilan yang dibuat dan Anda dapat melihat tajuk apa yang diminta olehAccess-Control-Request-Headers
Lionel Morrison

5
Opsi Konsol Pengembang bagus. Anda juga dapat menemukan apa yang Anda butuhkan dengan mendapatkan akses ke objek permintaan di server dan membuang nilai untuk header, tetapi secara khusus nilai header untuk "Header Akses-Kontrol-Permintaan-". Kemudian, salin / tempel ini ke response.setHeader Anda ("Access-Control-Allow-Headers", "{paste di sini}")
Software Prophets

7
contoh tolong!
Demodave

5
@ Demodave contoh ini untuk saya adalahheader("Access-Control-Allow-Headers: Content-Type")
Joshua Duxbury

1
@LionelMorrison, penggunaan alat dev chrome untuk header yang cocok. dijelaskan dengan baik !!!
Savina Chandla

119

Inilah yang perlu Anda tambahkan untuk membuatnya berfungsi.

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

Browser mengirimkan permintaan preflight (dengan jenis metode OPSI) untuk memeriksa apakah layanan yang dihosting di server diizinkan untuk diakses dari browser di domain yang berbeda. Menanggapi permintaan preflight jika Anda menyuntikkan header di atas, browser memahami bahwa tidak apa-apa untuk melakukan panggilan lebih lanjut dan saya akan mendapatkan respons yang valid untuk panggilan GET / POST saya yang sebenarnya. Anda dapat membatasi domain tempat akses diberikan dengan menggunakan Access-Control-Allow-Origin "," localhost, xvz.com "alih-alih *. (* akan memberikan akses ke semua domain)


7
Anda tidak dapat menggabungkan *untuk ...-Origindan trueuntuk ...-Credentials. Itu tidak akan gagal untuk permintaan non-kredensial, tetapi juga tidak akan berfungsi untuk permintaan kredensial. Lihat tautan yang saya poskan di jawaban saya.
Anne

Terima kasih Manish Arora, saya menggunakan solusi Anda dalam api saya dan itu berhasil. HttpContext.Response.Headers.Add ("Access-Control-Allow-Methods", "DAPATKAN, KEPALA, OPSI, POST, PUT"); HttpContext.Response.Headers.Add ("Access-Control-Allow-Headers", "Access-Control-Allow-Header, Asal, Menerima, X-Diminta-Dengan, Jenis-Konten, Akses-Kontrol-Permintaan-Metode, Akses -Control-Request-Headers "); HttpContext.Response.Headers.Add ("Access-Control-Allow-Origin", " localhost: 4200" );
Ramakrishnankt

1
Ini mengatakan sisi server semua munging header respons ini diperlukan karena "preflight"? Mengapa? Khusus untuk header standar sempurna? Setelah menggunakan HTTP untuk sementara, ini adalah berita bagi saya bahwa sangat banyak boilerplate diperlukan.
Samantha Atkins

@manish Saya memiliki serangkaian nilai yang berbeda untuk Access-Control-Allow-Header yang tidak berfungsi. Rangkaian nilai Anda berhasil. Terima kasih telah menghemat waktu dan frustrasi.
azakgaim

Apakah ada cara untuk wildcard beberapa header? Apakah itu ide buruk untuk wildcard semua header? Seperti response.setHeader("Access-Control-Allow-Headers", "*")? Apa implikasi keamanan dari melakukan ini?
Vadorequest

78

Masalah ini diselesaikan dengan

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

Khususnya dalam proyek saya (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();
});

Memperbarui:

Setiap kesalahan waktu: Access-Control-Allow-Headers is not allowed by itself in preflight responsekesalahan Anda dapat melihat apa yang salah dengan alat pengembang chrome :
masukkan deskripsi gambar di sini

kesalahan di atas tidak ada Content-Typesehingga tambahkan string Content-TypekeAccess-Control-Allow-Headers


1
Ini tidak akan bekerja untuk semua orang. Nilai untuk Header Akses-Kontrol-Permintaan-dapat bervariasi berdasarkan lingkungan. Dapatkan akses ke objek permintaan di server dan buang nilai untuk header "Access-Control-Request-Headers". Kemudian, salin / tempel ini ke response.setHeader Anda ("Access-Control-Allow-Headers", "{paste di sini}")
Software Prophets

1
Pastikan juga Anda mengeja Otorisasi cara amerika bukan cara Britsh. Itu setengah jam hidup saya, saya tidak akan kembali. Terima Kasih! [sigh]
geoidesic

14

Jawaban yang diterima ok, tapi saya kesulitan memahaminya. Jadi, inilah contoh sederhana untuk memperjelasnya.

Dalam permintaan ajax saya, saya memiliki header Otorisasi standar.

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

Kode ini menghasilkan kesalahan dalam pertanyaan. Apa yang harus saya lakukan di server nodejs saya adalah menambahkan Otorisasi di header yang diizinkan:

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

6

Untuk menambah jawaban lain. Saya memiliki masalah yang sama dan ini adalah kode yang saya gunakan di server ekspres saya untuk memungkinkan panggilan 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();
  }
});

Apa yang pada dasarnya dilakukan oleh kode ini adalah memotong semua permintaan dan menambahkan header CORS, kemudian melanjutkan dengan rute normal saya. Ketika ada permintaan PILIHAN, itu hanya merespons dengan tajuk CORS.

EDIT: Saya menggunakan perbaikan ini untuk dua server express nodejs terpisah pada mesin yang sama. Pada akhirnya saya memperbaiki masalah dengan server proxy sederhana.


Terima kasih! Bisakah Anda menguraikan bagaimana Anda menggunakan server proxy sederhana?
austin_ce

5

Saya sendiri mengalami masalah ini, dalam konteks ASP.NET pastikan Web.config Anda terlihat seperti ini:

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

Perhatikan nilai Otorisasi untuk Access-Control-Allow-Headerskunci tersebut. Saya kehilangan nilai Otorisasi, konfigurasi ini memecahkan masalah saya.


5

Sangat bagus saya menggunakan ini pada proyek 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
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
Badacadabra

4

Di Chrome:

Bidang header permintaan X-Diminta-Dengan tidak diizinkan oleh Access-Control-Allow-Header dalam respons preflight.

Bagi saya, kesalahan ini dipicu oleh spasi tambahan di URL panggilan ini.

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

3

Hanya untuk menambahkan bahwa Anda dapat menempatkan header itu juga ke file konfigurasi Webpack. Saya membutuhkan mereka seperti dalam kasus saya karena saya menjalankan server dev 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

Saya menerima kesalahan OP yang dinyatakan menggunakan Django, React, dan django-cors-header lib. Untuk memperbaikinya dengan tumpukan ini, lakukan hal berikut:

Di settings.py tambahkan di bawah ini per dokumentasi resmi .

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)

2

masalah ini terjadi ketika kami membuat tajuk khusus untuk permintaan. Permintaan ini yang menggunakan HTTP OPTIONS dan menyertakan beberapa tajuk.

Header yang diperlukan untuk permintaan ini adalah Access-Control-Request-Headers, yang harus menjadi bagian dari header respons dan harus memungkinkan permintaan dari semua asal. Kadang-kadang perlu Content-Typejuga di header respons. Jadi tajuk respons Anda harus seperti itu -

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

Dalam panggilan API Post, kami mengirim data dalam badan permintaan. Jadi jika kami akan mengirim data dengan menambahkan header tambahan apa pun ke panggilan API. Kemudian panggilan API OPSI pertama akan terjadi dan kemudian panggilan pos akan terjadi. Karena itu, Anda harus menangani panggilan API OPSI terlebih dahulu.

Anda dapat menangani masalah ini dengan menulis filter dan di dalamnya Anda harus memeriksa opsi panggilan API dan mengembalikan 200 status OK. Di bawah ini adalah kode contoh:

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

Jika Anda mencoba menambahkan tajuk khusus pada tajuk permintaan, Anda harus memberi tahu server bahwa tajuk tertentu diizinkan untuk terjadi. Tempat untuk melakukannya adalah di kelas yang memfilter permintaan. Dalam contoh yang ditunjukkan di bawah ini, nama header khusus adalah "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

Setelah menghabiskan hampir sehari, saya baru tahu bahwa menambahkan dua kode di bawah ini menyelesaikan masalah saya.

Tambahkan ini di Global.asax

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

dan di konfigurasi web tambahkan di bawah ini

<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

Saya juga menghadapi masalah yang sama di Angular 6. Saya memecahkan masalah dengan menggunakan kode di bawah ini. Tambahkan kode dalam file 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

Masalah yang sama yang saya hadapi.

Saya melakukan perubahan sederhana.

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

0

Pesan jelas bahwa 'Otorisasi' tidak diizinkan di API. Atur
Header Akses-Kontrol-Bolehkan: "Tipe Konten, Otorisasi"


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

Menambahkan kors dalam fungsi get Adalah yang bekerja untuk saya

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.