javascript - การตอบสนองต่อคำขอ preflight ไม่ผ่านการตรวจสอบการควบคุมการเข้าถึง - ไม่มีเฮดเดอร์ 'Access-Control-Allow-Origin'
ฉันได้รับข้อผิดพลาดนี้เมื่อใช้ ngResource เรียก REST API บน Amazon Web Services:
XMLHttpRequest ไม่สามารถโหลด http://server.apiurl.com:8000/s/login?login=facebook ได้ การตอบสนองต่อคำขอ preflight ไม่ผ่านการตรวจสอบการควบคุมการเข้าถึง: ไม่มีส่วนหัว 'Access-Control-Allow-Origin' ปรากฏบนทรัพยากรที่ร้องขอ ดังนั้นต้นกำเนิด 'http://localhost' จึงไม่ได้รับอนุญาตให้เข้าถึง ข้อผิดพลาด 405
บริการ :
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'
}
});
}]);
ตัวควบคุม:
[...]
loginService.getUser(JSON.stringify(fbObj)),
function (data) {
console.log(data);
},
function (result) {
console.error('Error', result.status);
}
[...]
ฉันกำลังใช้ Chrome ฉันสามารถทำอะไรได้อีกบ้างเพื่อแก้ปัญหานี้?
ฉันได้ตั้งค่าเซิร์ฟเวอร์ให้รับเฮดเดอร์จากแหล่งที่มา localhost แล้วด้วย
คำตอบ #1
คุณกำลังเจอปัญหา CORS
มีหลายวิธีในการแก้ไขหรือหาทางเลี่ยงปัญหานี้
- ปิด CORS ตัวอย่างเช่น: วิธีปิด CORS ใน Chrome
- ใช้ปลั๊กอินสำหรับเบราว์เซอร์ของคุณ
- ใช้พร็อกซี เช่น nginx ตัวอย่างวิธีตั้งค่า
- ทำขั้นตอนการติดตั้งที่จำเป็นสำหรับเซิร์ฟเวอร์ของคุณ นี่เป็นปัจจัยที่ขึ้นอยู่กับเว็บเซิร์ฟเวอร์ที่คุณติดตั้งบนอินสแตนซ์ EC2 ของคุณ (โดยสมมติว่านี่คือสิ่งที่คุณหมายถึงด้วย "บริการเว็บของ Amazon") สำหรับเซิร์ฟเวอร์เฉพาะของคุณ คุณสามารถอ้างอิงไปที่เว็บไซต์เปิดใช้งาน CORS
อย่างละเอียดมากขึ้น คุณกำลังพยายามเข้าถึง api.serverurl.com จาก localhost นี่คือคำนิยามที่แท้จริงของคำขอข้ามโดเมน
ไม่ว่าคุณจะปิดมันเพียงเพื่อทำงานให้เสร็จ (โอเค แต่จะมีความปลอดภัยต่ำสำหรับคุณถ้าคุณเข้าเว็บไซต์อื่นและมันก็แค่เลื่อนปัญหาไปข้างหน้า) หรือคุณสามารถใช้พร็อกซี่ที่ทำให้เบราว์เซอร์ของคุณคิดว่าคำขอทั้งหมดมาจากโฮสต์ท้องถิ่นในขณะที่จริงๆ แล้วคุณมีเซิร์ฟเวอร์ท้องถิ่นที่เรียกเซิร์ฟเวอร์ระยะไกล
ดังนั้น api.serverurl.com อาจกลายเป็น localhost:8000/api และ nginx ในเครื่องของคุณหรือพร็อกซีอื่นจะส่งไปยังปลายทางที่ถูกต้อง
ตอนนี้ตามคำเรียกร้องของผู้คน ข้อมูล CORS เพิ่มขึ้น 100%—รสชาติยอดเยี่ยมเช่นเดิม!
การข้าม CORS คือสิ่งที่แสดงให้เห็นสำหรับผู้ที่เพิ่งเริ่มเรียนด้านหน้า ตัวอย่าง HTTP กับ Promises
คำตอบ #2
เซิร์ฟเวอร์ "API" ของฉันเป็นแอปพลิเคชัน PHP ดังนั้นเพื่อแก้ปัญหานี้ฉันพบว่าวิธีแก้ปัญหาด้านล่างนี้สามารถใช้ได้:
วางบรรทัดเหล่านี้ในไฟล์ 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');
คำตอบ #3
ใน ASP.NET Core Web API ปัญหานี้ได้รับการแก้ไขโดยการเพิ่ม "Microsoft.AspNetCore.Cors" (เวอร์ชัน 1.1.1) และเพิ่มการเปลี่ยนแปลงดังต่อไปนี้ใน Startup.cs.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAllHeaders",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
.
.
.
}
และ
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Shows UseCors with named policy.
app.UseCors("AllowAllHeaders");
.
.
.
}
และการใส่ [EnableCors("AllowAllHeaders")] ในตัวควบคุม
คำตอบ #4
มีข้อควรระวังบางประการเกี่ยวกับ CORS ประการแรก มันไม่อนุญาตให้ใช้เครื่องหมายดอกจัน * แต่ก็อย่าเชื่อผมเป็นแน่แท้ ผมเคยอ่านที่ไหนสักแห่ง และตอนนี้หาบทความนั้นไม่เจอ
หากคุณกำลังส่งคำขอจากโดเมนที่แตกต่าง คุณจำเป็นต้องเพิ่มหัวข้อ allow origin
Access-Control-Allow-Origin: www.other.com
หากคุณกำลังส่งคำร้องขอที่มีผลต่อทรัพยากรของเซิร์ฟเวอร์เช่น POST/PUT/PATCH และหากประเภท MIME แตกต่างจาก application/x-www-form-urlencoded multipart/form-data หรือ text/plain เบราว์เซอร์จะทำการส่งคำร้อง OPTIONS แบบ pre-flight โดยอัตโนมัติเพื่อตรวจสอบกับเซิร์ฟเวอร์ว่ามันจะอนุญาตหรือไม่
ดังนั้น API/เซิร์ฟเวอร์ของคุณจำเป็นต้องจัดการคำขอ OPTIONS เหล่านี้อย่างเหมาะสม คุณจำเป็นต้องตอบกลับด้วย access control headers ที่เหมาะสม และรหัสสถานะการตอบสนอง HTTP ต้องเป็น 200
หัวข้อควรเป็นประมาณนี้ ปรับตามความต้องการของคุณ:
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
เฮดเดอร์ max-age เป็นสิ่งสำคัญ ในกรณีของฉัน มันจะไม่ทำงานถ้าไม่มีมัน ฉันเดาว่าเบราว์เซอร์ต้องการข้อมูลนี้เพื่อรู้ว่า "สิทธิ์การเข้าถึง" ใช้ได้เป็นเวลานานเท่าใด
นอกจากนี้ หากคุณกำลังส่งคำขอเช่น POST โดยใช้ application/json mime จากโดเมนที่แตกต่างกัน คุณยังต้องเพิ่มเฮดเดอร์ allow origin ที่กล่าวถึงก่อนหน้านี้ด้วย ดังนั้นมันจะมีลักษณะดังนี้:
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
เมื่อการตรวจสอบก่อนขึ้นบินสำเร็จและได้รับข้อมูลทั้งหมดที่จำเป็น คำร้องขอจริงของคุณจะถูกส่ง
โดยทั่วไป ไม่ว่าจะมีการร้องขอหัวข้อ Access-Control ใด ๆ ในคำขอเริ่มต้นหรือคำขอล่วงหน้า หัวข้อเหล่านั้นควรถูกตอบกลับในคำตอบเพื่อให้สามารถทำงานได้
มีตัวอย่างที่ดีในเอกสารของ MDN อยู่ที่ลิงก์นี้ และคุณก็ควรตรวจสอบโพสต์ Stack Overflow นี้ด้วย
คำตอบ #5
ถ้าคุณกำลังเขียนส่วนขยายของ Chrome
ในไฟล์ manifest.json คุณต้องเพิ่มสิทธิ์การเข้าถึงสำหรับโดเมนของคุณ
"permissions": [
"http://example.com/*",
"https://example.com/*",
"http://www.example.com/*",
"https://www.example.com/*"
]
คำตอบ #6
JavaScript XMLHttpRequest และ Fetch ปฏิบัติตามนโยบายต้นทางเดียวกัน ดังนั้น แอปพลิเคชันเว็บที่ใช้ XMLHttpRequest หรือ Fetch สามารถทำคำขอ HTTP ได้เฉพาะกับโดเมนของตัวเองเท่านั้น
ที่มา: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
คุณต้องส่งหัวข้อ HTTP Access-Control-Allow-Origin: * จากฝั่งเซิร์ฟเวอร์ของคุณ
ถ้าคุณกำลังใช้ Apache เป็นเซิร์ฟเวอร์ HTTP ของคุณ คุณสามารถเพิ่มมันลงในไฟล์การกำหนดค่า Apache ของคุณได้ดังนี้:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
Mod_headers ถูกเปิดใช้งานโดยค่าเริ่มต้นใน Apache อย่างไรก็ตาม คุณอาจต้องการตรวจสอบให้แน่ใจว่าถูกเปิดใช้งานโดยการรัน:
a2enmod headers
คำตอบ #7
ใน PHP คุณสามารถเพิ่ม headers ได้:
<?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: *");
...
คำตอบ #8
ในการแก้ไขปัญหาการร้องขอข้ามแหล่งที่มาในแอปพลิเคชัน Node.js:
npm i cors
และเพียงเพิ่มบรรทัดด้านล่างนี้ลงในไฟล์ app.js:
let cors = require('cors')
app.use(cors())
คำตอบ #9
หากคุณกำลังใช้เซิร์ฟเวอร์ IIS โดยบังเอิญ คุณสามารถตั้งค่าเฮดเดอร์ด้านล่างนี้ในตัวเลือกเฮดเดอร์คำขอ 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';
ด้วยสิ่งนี้ การทำงานของ POST, GET เป็นต้น จะทำงานได้ดี
