ค้นหาเว็บไซต์

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

มีหลายวิธีในการแก้ไขหรือหาทางเลี่ยงปัญหานี้

  1. ปิด CORS ตัวอย่างเช่น: วิธีปิด CORS ใน Chrome
  2. ใช้ปลั๊กอินสำหรับเบราว์เซอร์ของคุณ
  3. ใช้พร็อกซี เช่น nginx ตัวอย่างวิธีตั้งค่า
  4. ทำขั้นตอนการติดตั้งที่จำเป็นสำหรับเซิร์ฟเวอร์ของคุณ นี่เป็นปัจจัยที่ขึ้นอยู่กับเว็บเซิร์ฟเวอร์ที่คุณติดตั้งบนอินสแตนซ์ 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 เป็นต้น จะทำงานได้ดี

บทความที่เกี่ยวข้อง