Respons terhadap permintaan preflight tidak lulus pemeriksaan kontrol akses

458

Saya mendapatkan kesalahan ini menggunakan ngResource untuk memanggil REST API di Amazon Web Services:

XMLHttpRequest tidak dapat memuat http://server.apiurl.com:8000/s/login?login=facebook . Respons terhadap permintaan preflight tidak lulus pemeriksaan kontrol akses: Tidak ada tajuk 'Akses-Kontrol-Bolehkan-Asal' hadir pada sumber daya yang diminta. Karena itu, ' http: // localhost ' tidak diizinkan mengakses. Kesalahan 405

Layanan:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

Pengendali:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

Saya menggunakan Chrome, dan saya tidak tahu harus berbuat apa lagi untuk memperbaiki masalah ini. Saya bahkan sudah mengkonfigurasi server untuk menerima header dari asal localhost.

Andre Mendes
sumber
bingung: apakah Anda "mengkonfigurasi server" atau ini "api sisanya pada layanan web amazon"?
Dandavis
3
Anda jelas belum melakukan cukup untuk mengaktifkan CORS di sisi server. Posting contoh header tanggapan
charlietfl
4
Either way suara Anda salah. Dia meng-hosting file-nya di mesin lokalnya. Tidak masalah jenis conf yang dia lakukan di bagian belakang. Angular tidak akan mengizinkan penerbangan pra ini.
E. Maggini
3
Terima kasih atas komentarnya, itu berhasil ketika saya mengatur browser untuk mengaktifkan keamanan
Andre Mendes
1
@Andre Tapi mematikan keamanan hanyalah solusi buruk di mana Anda berkompromi dengan keamanan, tidak menyelesaikan masalah Anda ...
shivi

Jawaban:

241

Anda mengalami masalah CORS.

Ada beberapa cara untuk memperbaikinya.

  1. Matikan CORS. Misalnya: cara mematikan kors dalam chrome
  2. Gunakan plugin untuk browser Anda
  3. Gunakan proxy seperti nginx. contoh cara mengatur
  4. Pergi melalui pengaturan yang diperlukan untuk server Anda. Ini lebih merupakan faktor server web yang Anda muat pada instance EC2 Anda (anggap ini yang Anda maksud dengan "layanan web Amazon"). Untuk server spesifik Anda, Anda dapat merujuk ke situs web yang memungkinkan CORS.

Terlebih lagi, Anda mencoba mengakses api.serverurl.com dari localhost. Ini adalah definisi yang tepat dari permintaan lintas domain.

Dengan mematikannya hanya untuk menyelesaikan pekerjaan Anda (OK, berikan keamanan yang buruk untuk Anda jika Anda mengunjungi situs lain dan hanya menendang kaleng di ujung jalan) Anda dapat menggunakan proxy yang membuat browser Anda berpikir semua permintaan datang dari host lokal saat Anda benar-benar memiliki server lokal yang kemudian memanggil server jauh.

jadi api.serverurl.com mungkin menjadi localhost: 8000 / api dan nginx lokal Anda atau proksi lain akan mengirim ke tujuan yang benar.


Sekarang dengan permintaan populer, 100% lebih banyak info CORS .... rasanya luar biasa!


Dan untuk downvoters .... mem-bypass CORS adalah persis apa yang diperlihatkan bagi mereka yang hanya belajar ujung depan. https://codecraft.tv/courses/angular/http/http-with-promises/

E. Maggini
sumber
776
meninggalkan yang jelas menerapkan CORS dengan benar
charlietfl
40
Sangat mudah untuk memilih. Kurang mudah mengambil risiko sendiri temanku. Dan semua ini bekerja persis di lingkungan pengembang.
E. Maggini
3
Ini benar-benar berhasil. Saya menambahkan bendera untuk menonaktifkan keamanan Web. Karena perkembangannya baik-baik saja.
Andre Mendes
15
@charlietfl Bagaimana?
GreenAsJade
3
Terima kasih, kamu telah menyelamatkan hariku. Hanya digunakan opsi pertama: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. Dari: stackoverflow.com/questions/3102819/…
Harsimer
169

"API Server" saya adalah Aplikasi PHP sehingga untuk mengatasi masalah ini saya menemukan solusi di bawah ini untuk berfungsi:

Tempatkan baris di index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
Slipstream
sumber
3
Saya setuju, ini lebih baik daripada jawaban yang diterima meskipun hati-hati saat menyalin garis-garis ini, pastikan untuk memodifikasi metode dan asal.
Amir Savand
11
Di mana menempatkannya dalam proyek 6 Angular?
whatthefish
@CodyBugstein dan whatthefish menempatkan sebelum output apa pun
Garet Claborn
Aplikasi klien saya berhenti berfungsi ketika saya menambahkan header yang hanya diperlukan oleh beberapa server. Jika permintaan menyertakan header khusus, mereka harus didaftar Access-Control-Allow-Headers.
z0r
47

Di api web AspNetCore, masalah ini diperbaiki dengan menambahkan "Microsoft.AspNetCore.Cors" (ver 1.1.1) dan menambahkan perubahan di bawah ini pada Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

dan

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

dan memakai [EnableCors("AllowAllHeaders")]pengontrol.

Rajkumar Peter
sumber
18
Ini adalah jawaban yang bagus jika Anda ingin membangun kerentanan skrip lintas situs! Tolong jangan pernah melakukan ini! Tentukan domain Anda yang dapat Anda akses untuk menghindari masalah keamanan. CORS ada karena suatu alasan.
paqogomez
2
Hanya untuk memperjelas @paqogomez, dalam metode ConfigureServices Anda: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.DenganOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyOrigin (). AllowAnyMethod ();});}); dan dalam metode Konfigurasi Anda: app.UseCors ("AllowSpecificOrigin");
Francisco Tena
28

Ada beberapa peringatan tentang CORS. Pertama, itu tidak memungkinkan wildcard *tetapi jangan pegang yang ini saya sudah membacanya di suatu tempat dan saya tidak dapat menemukan artikel sekarang.

Jika Anda membuat permintaan dari domain lain, Anda perlu menambahkan perbolehkan header asal.

 Access-Control-Allow-Origin: www.other.com 

Jika Anda membuat permintaan yang mempengaruhi sumber daya server seperti POST / PUT / PATCH, dan jika jenis mime berbeda dari berikut ini application/x-www-form-urlencoded, multipart/form-dataatau text/plainbrowser secara otomatis akan membuat PILIHAN pre-flight meminta untuk memeriksa dengan server jika itu akan memungkinkan .

Jadi API / server Anda perlu menangani permintaan PILIHAN ini sesuai, Anda harus merespons dengan yang sesuai access control headersdan kode status tanggapan http perlu 200.

Tajuknya harus seperti ini, sesuaikan dengan kebutuhan Anda:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Header usia maks penting, dalam kasus saya, tidak akan berfungsi tanpanya, saya kira browser perlu info untuk berapa lama "hak akses" valid.

Selain itu, jika Anda membuat mis. POSTPermintaan dengan application/jsonpantomim dari domain lain, Anda juga perlu menambahkan tajuk asal diizinkan yang disebutkan sebelumnya, sehingga akan terlihat seperti ini:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Ketika pra-penerbangan berhasil dan mendapatkan semua informasi yang dibutuhkan permintaan Anda yang sebenarnya akan dibuat.

Secara umum, Access-Controlheader apa pun yang diminta dalam permintaan awal atau pra-penerbangan, harus diberikan dalam respons agar dapat berfungsi.

Ada contoh yang bagus dalam dokumen MDN di sini di tautan ini , dan Anda juga harus memeriksa pos SO ini

Sasa Blagojevic
sumber
1
Berikut ini adalah artikel Mozilla yang berbicara tentang bagaimana Anda tidak dapat menggunakan wildcard untuk asal kors: Tautan Jadi tampaknya ini hanya berlaku ketika menggunakan kredensial (jika saya mengerti dengan benar)
Helzgate
Saya menggunakan wildcard dan mengirimkan token pembawa untuk mengesahkan permintaan dan itu berfungsi dengan baik sehingga tidak yakin apa tautan yang saya berikan di atas mengacu pada kredensial. Masalah saya adalah bahwa ketika mem-bulding kebijakan CORS saya di .Net Core saya tidak menambahkan .AllowCredentials(). Setelah menambahkan .AllowCredentials()semuanya berhasil.
Helzgate
15

JavaScript XMLHttpRequest dan Fetch ikuti kebijakan asal-sama. Jadi, aplikasi web menggunakan XMLHttpRequest atau Fetch hanya bisa membuat permintaan HTTP ke domainnya sendiri.

Sumber: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Anda harus mengirim Access-Control-Allow-Origin: * HTTP header dari sisi server Anda.

Jika Anda menggunakan Apache sebagai server HTTP Anda, maka Anda dapat menambahkannya ke file konfigurasi Apache Anda seperti ini:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers diaktifkan secara default di Apache, namun, Anda mungkin ingin memastikan itu diaktifkan dengan menjalankan:

 a2enmod headers
Tadej
sumber
Di mana saya dapat menemukan file konfigurasi Apache saya?
Shubham Arya
@ShubhamArya di linux Debian lokasi default adalah:/etc/apache2/apache2.conf
Tadej
di mana saya bisa menemukannya di windows?
Shubham Arya
10

Jika Anda menulis ekstensi chrome

Anda harus menambahkan manifest.jsonizin untuk domain Anda.

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
freedev
sumber
1
Periksa juga apakah Anda memiliki awalan www
Vlas Bashynskyi
8

Jika Anda menggunakan server IIS secara kebetulan. Anda dapat mengatur tajuk di bawah ini dalam opsi tajuk permintaan HTTP.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

dengan ini semua posting, dapatkan dll, akan berfungsi dengan baik.

Sunil Kumar
sumber
5

Di PHP Anda dapat menambahkan header:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...
atiruz
sumber
terima kasih, itu berhasil untuk saya! dalam pengujian dan lingkungan produksi. Bahkan menggunakan https: //
Jose Seie
1
@atiruz Terima kasih atas solusinya. Ini Bekerja Ketika saya menambahkan barisheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD
5

Untuk memperbaiki masalah lintas-asal-permintaan dalam aplikasi Node JS:

npm i cors

Dan cukup tambahkan baris di bawah ini ke app.js

let cors = require('cors')
app.use(cors())
Rohit Parte
sumber
3
ini hanya bekerja di aplikasi js express, tidak semua aplikasi node
DrCord
3

Dalam file konfigurasi Apache VirtualHost saya, saya telah menambahkan baris berikut:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
hugsbrugs
sumber
3

Untuk mereka yang menggunakan Proxy Terintegrasi Lambda dengan API Gateway . Anda perlu mengonfigurasi fungsi lambda Anda seolah-olah Anda mengirimkan permintaan Anda secara langsung, artinya fungsi tersebut harus mengatur header respons dengan benar. (Jika Anda menggunakan fungsi lambda khusus, ini akan ditangani oleh API Gateway.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
sumber
1
Saya ingin juga berpadu dan menyebutkan satu gotcha besar saya tidak berpikir dokumen AWS. Katakanlah Anda menggunakan API gateway untuk mem-proksi fungsi lambda Anda, dan Anda menggunakan beberapa API dalam fungsi lambda itu. Jika API itu mengembalikan kode keberhasilan non-200 dan Anda tidak menambahkan kode keberhasilan non-200 ke dalam respons metode di gateway API, maka Anda akan menerima kesalahan dan tidak melihat respons sukses Anda . Contoh untuk ini: Sendgrid dan Twilio memiliki kode keberhasilan non-200.
Stephen Tetreault
3

Saya pikir menonaktifkan CORS dari Chrome bukanlah cara yang baik , karena jika Anda menggunakannya dalam ion, tentu saja di Mobile Build masalah ini akan meningkat lagi.

Jadi lebih baik untuk Memperbaiki di Backend Anda.

Pertama-tama Dalam header, Anda perlu mengatur-

  • header ('Access-Control-Allow-Origin: *');
  • header ('Header set Access-Control-Allow-Header: "Asal, X-Diminta-Dengan, Tipe-Konten, Terima"');

Dan jika API berperilaku sebagai GET dan POST keduanya maka juga Set di header- Anda

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header ("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header ("Header Akses-Kontrol-Bolehkan:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); keluar (0); }

Shubham Pandey
sumber
3

Penyebab yang sangat umum dari kesalahan ini adalah bahwa host API telah memetakan permintaan ke metode http (mis. PUT) dan klien API memanggil API menggunakan metode http yang berbeda (mis. POST atau GET)

Christian Nwafor
sumber
Saya menerapkan CORS dengan benar di server saya, tetapi saya lupa menambahkan PUTmetode
fguillen
3

Tim kami sesekali melihat ini menggunakan Vue, aksioma dan C # WebApi. Menambahkan atribut rute pada titik akhir yang Anda coba lakukan perbaikan untuk kami.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
sumber
Kami tidak begitu yakin mengapa. Lol. Jika ada yang memberi tahu saya!
w00ngy
1

Saya menghadapi masalah ini ketika server DNS diatur ke 8.8.8.8 (milik Google). Sebenarnya, masalahnya ada di router, aplikasi saya mencoba terhubung dengan server melalui google, bukan secara lokal (untuk kasus khusus saya). Saya telah menghapus 8.8.8.8 dan ini menyelesaikan masalah. Saya tahu bahwa masalah ini diselesaikan dengan pengaturan CORS, tetapi mungkin seseorang akan memiliki masalah yang sama dengan saya

Kirill Gusyatin
sumber
1

Saya menggunakan AWS SDK untuk unggahan, setelah menghabiskan waktu mencari secara online saya menemukan utas ini. terima kasih kepada @lsimoneau 45581857 ternyata hal yang persis sama terjadi. Saya hanya mengarahkan Url permintaan saya ke wilayah pada ember saya dengan melampirkan opsi wilayah dan itu berhasil.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
sumber
0

Distribusi mandiri GeoServer termasuk server aplikasi Jetty. Aktifkan Cross-Origin Resource Sharing (CORS) untuk memungkinkan aplikasi JavaScript di luar domain Anda menggunakan GeoServer.

Batalkan komentar berikut <filter>dan <filter-mapping>dari webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Yassine Ech-Charafi
sumber
Itu tidak menambahkan antyhing ke header respons, sehingga tidak berfungsi
JollyRoger
1
tidak menggunakan GeoServer, tetapi klip ini membantu saya mengetahui pengaturan yang harus saya gunakan pada aplikasi yang menerima panggilan.
Matt Felzani
0

Sangat mudah untuk menyelesaikan masalah ini hanya dengan beberapa langkah mudah, tanpa khawatir tentang apa pun. Mohon, Ikuti langkah-langkah untuk menyelesaikannya.

  1. buka ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. pergi ke instalasi dan salin perintah npm install cors untuk menginstal melalui terminal node
  3. buka Penggunaan Sederhana (Aktifkan Semua Permintaan CORS) dengan menggulir. lalu salin dan tempel pernyataan lengkap di proyek Anda dan jalankan ... yang pasti akan berhasil .. salin kode komentar dan tempel di app.js Anda atau tempel lainnya memproyeksikan dan mencoba .. ini akan bekerja. ini akan membuka setiap sumber daya berbagi lintas .. jadi kita dapat beralih antara melayani untuk Anda gunakan
Rahul sah
sumber
1
var express = butuhkan ('express') var cors = butuhkan ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', fungsi (req, res, selanjutnya) {res.json ({msg: 'Ini memungkinkan CORS untuk semua asal!'})}) app.listen (80, function () {console.log ('server web berkemampuan CORS mendengarkan pada port 80' )})
Rahul sah
-1

Sesuatu yang sangat mudah dilewatkan ...

DI penjelajah solusi, klik kanan proyek api. Di jendela properti atur 'Otentikasi Anonim' ke Diaktifkan !!!

Wes
sumber
-8

Nonaktifkan keamanan chrome. Buat pintasan chrome klik kanan -> properti -> target, rekatkan ini "C: \ Program Files (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user --user -data-dir = "c: / chromedev"

Nithin
sumber