เหตุใดรหัส JavaScript ของฉันจึงได้รับข้อผิดพลาด“ No 'Access-Control-Allow-Origin' อยู่ในทรัพยากรที่ร้องขอ” ในขณะที่บุรุษไปรษณีย์ไม่ได้รับ

Nov 18 2013

หมายเหตุ Mod : คำถามนี้เกี่ยวกับสาเหตุที่บุรุษไปรษณีย์ไม่อยู่ภายใต้ข้อ จำกัด CORS ในลักษณะเดียวกับ XMLHttpRequest คำถามนี้ไม่เกี่ยวกับวิธีแก้ไขข้อผิดพลาด "No" Access-Control-Allow-Origin "... "

กรุณาหยุดโพสต์ :

  • การกำหนดค่า CORS สำหรับทุกภาษา / กรอบภายใต้ดวงอาทิตย์ แทนที่จะหา / คำถามกรอบของภาษาที่เกี่ยวข้องของคุณ
  • บริการของบุคคลที่สามที่อนุญาตให้มีการร้องขอเพื่อหลีกเลี่ยง CORS
  • ตัวเลือกบรรทัดคำสั่งสำหรับปิด CORS สำหรับเบราว์เซอร์ต่างๆ

ฉันกำลังพยายามที่จะทำการอนุญาตใช้งาน JavaScriptโดยการเชื่อมต่อไปยังสงบ APIในตัวขวด อย่างไรก็ตามเมื่อฉันร้องขอฉันได้รับข้อผิดพลาดต่อไปนี้:

XMLHttpRequest ไม่สามารถโหลดhttp: // myApiUrl / เข้าสู่ระบบ ไม่มีส่วนหัว "Access-Control-Allow-Origin" ในทรัพยากรที่ร้องขอ Origin 'null' จึงไม่อนุญาตให้เข้าถึง

ฉันรู้ว่า API หรือทรัพยากรระยะไกลต้องตั้งค่าส่วนหัว แต่ทำไมมันไม่ทำงานเมื่อฉันทำคำขอผ่านทางส่วนขยายของ Chrome Postman ?

นี่คือรหัสคำขอ:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

คำตอบ

1404 MD.SahibBinMahboob Nov 18 2013 at 02:49

ถ้าฉันเข้าใจถูกต้องคุณกำลังทำXMLHttpRequestไปยังโดเมนอื่นที่ไม่ใช่เพจของคุณ ดังนั้นเบราว์เซอร์จึงปิดกั้นเนื่องจากโดยปกติจะอนุญาตให้มีการร้องขอในต้นทางเดียวกันด้วยเหตุผลด้านความปลอดภัย คุณต้องทำสิ่งที่แตกต่างออกไปเมื่อคุณต้องการทำคำขอข้ามโดเมน กวดวิชาเกี่ยวกับวิธีการเพื่อให้บรรลุว่าคือการใช้ล ธ

เมื่อคุณใช้บุรุษไปรษณีย์นโยบายนี้จะไม่ถูก จำกัด อ้างจากCross-Origin XMLHttpRequest :

หน้าเว็บปกติสามารถใช้อ็อบเจ็กต์ XMLHttpRequest เพื่อส่งและรับข้อมูลจากเซิร์ฟเวอร์ระยะไกลได้ แต่จะถูก จำกัด โดยนโยบายต้นทางเดียวกัน ส่วนขยายไม่ จำกัด ส่วนขยายสามารถพูดคุยกับเซิร์ฟเวอร์ระยะไกลนอกจุดเริ่มต้นได้ตราบใดที่ส่วนขยายนั้นขอสิทธิ์ข้ามแหล่งที่มาก่อน

266 ShadyMohamedSherif Dec 04 2014 at 03:24

คำเตือน:การใช้Access-Control-Allow-Origin: *อาจทำให้ API / เว็บไซต์ของคุณเสี่ยงต่อการโจมตีด้วยการปลอมแปลงคำขอข้ามไซต์ (CSRF) ตรวจสอบให้แน่ใจว่าคุณเข้าใจความเสี่ยงก่อนที่จะใช้รหัสนี้

มันง่ายมากที่จะแก้หากคุณกำลังใช้PHP เพียงเพิ่มสคริปต์ต่อไปนี้ในส่วนเริ่มต้นของหน้า PHP ของคุณซึ่งจัดการคำขอ:

<?php header('Access-Control-Allow-Origin: *'); ?>

หากคุณใช้Node-redคุณต้องอนุญาตCORSในnode-red/settings.jsไฟล์โดยยกเลิกการแสดงความคิดเห็นในบรรทัดต่อไปนี้:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

หากคุณใช้Flaskเหมือนกับคำถาม คุณต้องติดตั้งก่อนflask-cors

$ pip install -U flask-cors

จากนั้นรวมคอร์ขวดในแอปพลิเคชันของคุณ

from flask_cors import CORS

แอปพลิเคชั่นง่ายๆจะมีลักษณะดังนี้:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

สำหรับรายละเอียดเพิ่มเติมคุณสามารถตรวจสอบเอกสารขวด

68 GeorgeLivingston Dec 13 2016 at 20:02

เนื่องจาก
$ .ajax ({type: "POST" - เรียกOPTIONS
$ .post ( - เรียกPOST

ทั้งสองอย่างแตกต่างกัน บุรุษไปรษณีย์เรียก "POST" อย่างถูกต้อง แต่เมื่อเราเรียกมันจะเป็น "OPTIONS"

สำหรับบริการเว็บ C # - Web API

โปรดเพิ่มรหัสต่อไปนี้ในไฟล์web.configของคุณภายใต้แท็ก <system.webServer> สิ่งนี้จะได้ผล:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

โปรดตรวจสอบว่าคุณไม่ได้ทำผิดพลาดในการโทร Ajax

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

หมายเหตุ:หากคุณกำลังมองหาเนื้อหาที่ดาวน์โหลดจากเว็บไซต์ของบุคคลที่สามแล้วนี้จะไม่ช่วยให้คุณ คุณสามารถลองใช้รหัสต่อไปนี้ แต่ไม่ใช่ JavaScript

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
17 KamilKiełczewski Dec 16 2019 at 16:06

ในการตรวจสอบด้านล่างในฐานะ API ฉันใช้http://example.comแทนhttp: // myApiUrl / loginจากคำถามของคุณเพราะอันแรกใช้ได้

ฉันคิดว่าหน้าของคุณอยู่ในhttp: //my-site.local: 8088

สาเหตุที่คุณเห็นผลลัพธ์ที่แตกต่างกันคือบุรุษไปรษณีย์:

  • ตั้งค่าส่วนหัวHost=example.com(API ของคุณ)
  • ไม่ได้ตั้งค่าส่วนหัว Origin

วิธีนี้คล้ายกับวิธีการส่งคำขอของเบราว์เซอร์เมื่อไซต์และ API มีโดเมนเดียวกัน (เบราว์เซอร์ตั้งค่ารายการส่วนหัวReferer=http://my-site.local:8088ด้วย แต่ฉันไม่เห็นใน Postman) เมื่อไม่ได้ตั้งค่าOriginส่วนหัวโดยปกติเซิร์ฟเวอร์จะอนุญาตการร้องขอดังกล่าวโดยค่าเริ่มต้น

นี่เป็นวิธีมาตรฐานในการส่งคำขอของบุรุษไปรษณีย์ แต่เบราว์เซอร์จะส่งคำขอต่างออกไปเมื่อไซต์และ API ของคุณมีโดเมนที่แตกต่างกันจากนั้นCORSจะเกิดขึ้นและเบราว์เซอร์โดยอัตโนมัติ:

  • ตั้งค่าส่วนหัวHost=example.com(ของคุณเป็น API)
  • ตั้งค่าส่วนหัวOrigin=http://my-site.local:8088(ไซต์ของคุณ)

(ส่วนหัวRefererมีค่าเดียวกับOrigin) และตอนนี้ในแท็บคอนโซลและเครือข่ายของ Chrome คุณจะเห็น:

เมื่อคุณมีHost != Originนี้คือ ธ และเมื่อเซิร์ฟเวอร์ตรวจพบการร้องขอดังกล่าวก็มักจะบล็อกได้โดยเริ่มต้นที่

Origin=nullถูกตั้งค่าเมื่อคุณเปิดเนื้อหา HTML จากโลคัลไดเร็กทอรีและจะส่งคำขอ สถานการณ์เดียวกันคือเมื่อคุณส่งคำขอภายใน an <iframe>เช่นเดียวกับในตัวอย่างด้านล่าง (แต่ที่นี่Hostไม่ได้ตั้งค่าส่วนหัวเลย) - โดยทั่วไปแล้วทุกที่ที่ข้อกำหนด HTML ระบุว่าแหล่งกำเนิดทึบคุณสามารถแปลสิ่งนั้นเป็นOrigin=nullได้ ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้คุณสามารถหาได้ที่นี่

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

หากคุณไม่ได้ใช้ง่ายล ธ ขอมักเบราว์เซอร์โดยอัตโนมัตินอกจากนี้ยังส่ง OPTIONS ขอก่อนที่จะส่งคำขอหลัก - ข้อมูลเพิ่มเติมที่นี่ ตัวอย่างด้านล่างแสดงให้เห็น:

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

คุณสามารถเปลี่ยนการกำหนดค่าเซิร์ฟเวอร์ของคุณเพื่ออนุญาตคำขอ CORS

นี่คือตัวอย่างการกำหนดค่าที่เปิดCORS บน nginx (ไฟล์ nginx.conf) - โปรดใช้ความระมัดระวังในการตั้งค่าalways/"$http_origin"สำหรับ nginx และ"*"สำหรับ Apache ซึ่งจะปลดบล็อก CORS จากโดเมนใดก็ได้

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

นี่คือตัวอย่างการกำหนดค่าที่เปิดCORS บน Apache (ไฟล์. htaccess)

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

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

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

12 Gopinath Feb 02 2020 at 17:27

การใช้ข้อ จำกัด ธ เป็นคุณลักษณะการรักษาความปลอดภัยที่กำหนดโดยเซิร์ฟเวอร์และดำเนินการโดยเบราว์เซอร์

เบราว์เซอร์ดูนโยบาย CORS ของเซิร์ฟเวอร์และเคารพ

อย่างไรก็ตามเครื่องมือ Postman ไม่ได้กังวลเกี่ยวกับนโยบาย CORS ของเซิร์ฟเวอร์

นั่นคือสาเหตุที่ข้อผิดพลาด CORS ปรากฏในเบราว์เซอร์ แต่ไม่ใช่ในบุรุษไปรษณีย์

8 Kms Mar 11 2020 at 00:34

พบข้อผิดพลาดเดียวกันในกรณีการใช้งานที่แตกต่างกัน

Use Case:ใน chrome เมื่อพยายามเรียก Spring REST end point ในเชิงมุม

วิธีแก้ไข:เพิ่มคำอธิบายประกอบ@CrossOrigin ("*")ที่ด้านบนของคลาสคอนโทรลเลอร์ตามลำดับ

3 Adwaith Jul 22 2020 at 00:06

หากคุณต้องการที่จะข้ามข้อ จำกัด ว่าเมื่อดึงเนื้อหาที่มีการดึงข้อมูล API หรือ XMLHttpRequest ใน javascript, คุณสามารถใช้พร็อกซีเซิร์ฟเวอร์เพื่อที่จะกำหนดส่วนหัวไปAccess-Control-Allow-Origin*

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/fetch', (req, res) => {
  request(
    { url: req.query.url },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).send('error');
      }
      res.send(body);
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

ด้านบนคือโค้ดตัวอย่าง (ต้องมีโหนด Js) ซึ่งสามารถทำหน้าที่เป็นพร็อกซีเซิร์ฟเวอร์ได้ ตัวอย่างเช่น: หากฉันต้องการดึงข้อมูลhttps://www.google.comตามปกติข้อผิดพลาด CORS จะถูกส่งไป แต่ตอนนี้เนื่องจากคำขอถูกส่งผ่านพร็อกซีเซิร์ฟเวอร์ที่โฮสต์ในเครื่องที่พอร์ต 3000 พร็อกซีเซิร์ฟเวอร์จะเพิ่มAccess-Control-Allow-Originส่วนหัวในการตอบกลับและจะไม่มีปัญหาใด ๆ

ส่งคำขอ GET ไปที่ http: // localhost: 3000 / fetch? url = Your URL hereแทนที่จะส่งคำขอไปยัง URl ที่คุณต้องการดึงข้อมูลโดยตรง

Your URL here ย่อมาจาก URL ที่คุณต้องการดึงข้อมูลเช่น: https://www.google.com

ShaktiSrivastav Apr 18 2020 at 23:12

สำหรับโครงการ. NET Core Web API เท่านั้นให้เพิ่มการเปลี่ยนแปลงต่อไปนี้:

  1. เพิ่มรหัสต่อไปนี้หลังservices.AddMvc()บรรทัดในConfigureServices()วิธีการของไฟล์ Startup.cs:
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. เพิ่มรหัสต่อไปนี้หลังapp.UseMvc()บรรทัดในConfigure()วิธีการของไฟล์ Startup.cs:
app.UseCors(options => options.AllowAnyOrigin());
  1. เปิดตัวควบคุมที่คุณต้องการเข้าถึงภายนอกโดเมนและเพิ่มแอตทริบิวต์ต่อไปนี้ที่ระดับคอนโทรลเลอร์:
[EnableCors("AllowOrigin")]