ส่วนหัว Access-Control-Allow-Origin ทำงานอย่างไร


1152

เห็นได้ชัดว่าฉันเข้าใจผิดความหมายทั้งหมด ฉันคิดถึงบางสิ่งเช่นนี้:

  1. ดาวน์โหลดไคลเอนต์จาวาสคริปต์ MyCode.js โค้ดจากhttp://siteA- ต้นกำเนิด
  2. ส่วนหัวการตอบสนองของ MyCode.js มีAccess-Control-Allow-Origin:http://siteBซึ่งฉันคิดว่าหมายความว่า MyCode.js ได้รับอนุญาตให้ทำการอ้างอิงข้ามแหล่งที่มากับเว็บไซต์ B
  3. ไคลเอนต์ทริกเกอร์การทำงานบางอย่างของ MyCode.js ซึ่งจะทำการร้องขอhttp://siteBซึ่งควรจะดีแม้จะเป็นคำขอข้ามแหล่ง

ฉันผิด มันไม่ทำงานเช่นนี้เลย ดังนั้นฉันได้อ่านการแชร์ทรัพยากรข้ามแหล่งและพยายามอ่านการแบ่งปันทรัพยากรข้ามแหล่งในการแนะนำ w3c

มีสิ่งหนึ่งที่แน่นอน - ฉันยังไม่เข้าใจว่าฉันควรใช้ส่วนหัวนี้อย่างไร

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

PS

ฉันไม่ต้องการใช้ JSONP


3
ฉันไม่แน่ใจ แต่ฉันเชื่อว่าการตั้งค่าส่วนหัวในลักษณะนี้จะทำให้สามารถเรียกรหัสบนไซต์ B http://siteA/MyCode.jsได้
pimvdb

6
แต่อย่างไร เพื่อให้ได้ค่าส่วนหัวเราต้องดึงทรัพยากรก่อน แต่ทรัพยากรเป็นจุดกำเนิดข้ามและเบราว์เซอร์ไม่ควรบล็อกคำขอตั้งแต่แรก?
ทำเครื่องหมาย

สิ่งที่คุณอธิบายจริงคล้ายกับการปฏิบัติอื่นนโยบายความปลอดภัยของเนื้อหา
อเล็กซ์

3
@mark คุณไม่จำเป็นต้องดึงทรัพยากรเพื่อรับส่วนหัว วิธี HTTP HEADER จะส่งคืนเฉพาะส่วนหัว และในกรณีของ CORS การตรวจสอบ preflight เสร็จแล้วโดยใช้วิธี HTTP OPTIONS ซึ่งไม่ส่งคืนเนื้อความเช่นกัน คำตอบ apsillers อธิบายstackoverflow.com/posts/10636765/revisionsอย่างนี้
Matthew

คำตอบ:


1445

Access-Control-Allow-Originเป็นส่วนหัว CORS (การแบ่งปันทรัพยากรข้ามแหล่งกำเนิด)ส่วนหัวล

เมื่อไซต์ A พยายามดึงเนื้อหาจากไซต์ B ไซต์ B สามารถส่ง Access-Control-Allow-Originส่วนหัวการตอบกลับเพื่อบอกเบราว์เซอร์ว่าเนื้อหาของหน้านี้สามารถเข้าถึงได้จากจุดเริ่มต้นที่แน่นอน (เป็นแหล่งกำเนิดเป็นโดเมนรวมทั้งโครงการและพอร์ตหมายเลข .) โดยค่าเริ่มต้นหน้าเว็บไซต์ B คือไม่สามารถเข้าถึงแหล่งกำเนิดอื่น ๆ ; การใช้Access-Control-Allow-Originส่วนหัวจะเป็นการเปิดประตูสำหรับการเข้าถึงข้ามแหล่งกำเนิดโดยการร้องขอต้นกำเนิดที่เฉพาะเจาะจง

สำหรับแต่ละทรัพยากร / หน้าเว็บที่ไซต์ B ต้องการให้เข้าถึงไซต์ A ไซต์ B ควรแสดงหน้าเว็บด้วยส่วนหัวการตอบกลับ:

Access-Control-Allow-Origin: http://siteA.com

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

คำขอที่ไม่ง่าย

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

  • ใช้กริยา HTTP อื่นที่ไม่ใช่ GET หรือ POST (เช่น PUT, DELETE)
  • ใช้ส่วนหัวคำขอที่ไม่ง่าย ส่วนหัวคำของ่าย ๆ เท่านั้นคือ:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(นี้เป็นเรื่องง่ายเฉพาะเมื่อค่าที่เป็นapplication/x-www-form-urlencoded, multipart/form-dataหรือtext/plain)

หากเซิร์ฟเวอร์ตอบสนองต่อ preflight OPTIONS พร้อมส่วนหัวการตอบสนองที่เหมาะสม (Access-Control-Allow-Headersสำหรับไม่ใช่แบบง่ายAccess-Control-Allow-Methodsสำหรับคำกริยาที่ไม่ใช่เรื่องง่าย) ที่ตรงกับคำกริยาที่ไม่ใช่เรื่องง่ายและ / หรือส่วนหัวที่ไม่ใช่เรื่องง่ายเบราว์เซอร์ส่งคำขอจริง

เผื่อว่าที่ไซต์ต้องการเพื่อส่งคำร้องขอวาง/somePageด้วยไม่ใช่ง่ายๆContent-Typeค่าของapplication/jsonเบราว์เซอร์ก่อนจะส่งคำร้องขอ preflight:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

โปรดทราบว่าAccess-Control-Request-MethodและAccess-Control-Request-Headersจะถูกเพิ่มโดยเบราว์เซอร์โดยอัตโนมัติ คุณไม่จำเป็นต้องเพิ่มพวกเขา ตัวเลือก preflight นี้ได้รับส่วนหัวการตอบสนองที่ประสบความสำเร็จ:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

เมื่อส่งคำขอจริง (หลังจากเสร็จสิ้นการ preflight) พฤติกรรมจะเหมือนกับวิธีการจัดการคำร้องขอแบบง่าย กล่าวอีกนัยหนึ่งคำขอที่ไม่ง่ายซึ่งสำเร็จ preflight จะถือว่าเหมือนกับคำของ่าย ๆ (กล่าวคือเซิร์ฟเวอร์จะต้องส่งAccess-Control-Allow-Originอีกครั้งเพื่อตอบสนองจริง)

เบราว์เซอร์ส่งคำขอจริง:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

และเซิร์ฟเวอร์จะส่งกลับAccess-Control-Allow-Originเช่นเดียวกับการร้องของ่ายๆ:

Access-Control-Allow-Origin: http://siteA.com

ดูที่การทำความเข้าใจ XMLHttpRequest ผ่าน CORSสำหรับข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับคำขอที่ไม่ธรรมดา


4
แต่ MyCode.js ไม่สามารถเข้าถึงไซต์ B ได้ตั้งแต่แรก! ส่วนหัวนี้จะมาถึงลูกค้าอย่างไร BTW รุ่งโรจน์สำหรับเครื่องร่อนแสงชีวิตในอวตาร
ทำเครื่องหมาย

8
ฉันแก้ไขด้วยการชี้แจง: เบราว์เซอร์ทำการดึงข้อมูลเครือข่ายบนไซต์ B เพื่อตรวจสอบAccess-Control-Allow-Originส่วนหัว แต่อาจไม่ให้การตอบสนองต่อรหัส JS บนไซต์ A หากส่วนหัวไม่อนุญาตให้ไซต์ A มี (ขอบคุณ PS :))
apsillers

2
อันที่จริงฉันไม่เห็นบันทึกการดาวน์โหลดใน Fiddler เว้นแต่ว่าคำขอข้ามทางจะได้รับการอนุมัติ น่าสนใจ ...
ทำเครื่องหมาย

23
@ Jwan622 คำถาม " ทำไม? " พื้นฐานเช่นนั้นอาจไม่อยู่ในขอบเขตสำหรับคำตอบเฉพาะนี้ซึ่งเป็นเพียงเกี่ยวกับกฎและกลไก โดยทั่วไปเบราว์เซอร์ช่วยให้คุณซึ่งเป็นมนุษย์นั่งอยู่ที่คอมพิวเตอร์มองเห็นแหล่งข้อมูลใด ๆ จากแหล่งกำเนิดใด ๆ มันไม่อนุญาตให้สคริปต์ (ซึ่งทุกคนสามารถเขียนได้) จากการอ่านทรัพยากรจากต้นกำเนิดที่แตกต่างจากที่มาของหน้าเว็บที่เรียกใช้สคริปต์ บางคำถามที่เกี่ยวข้องคือprogrammers.stackexchange.com/q/216605และรูปแบบการคุกคามสำหรับนโยบายกำเนิดเดียวกันคืออะไร
apsillers

3
ในกรณีที่ใช้การรับรองความถูกต้องAccess-Control-Allow-Originไม่ยอมรับ*บางเบราว์เซอร์ (FF และ Chrome AFAIK) ดังนั้นในกรณีนี้คุณต้องระบุค่าจากOriginส่วนหัว หวังว่านี่จะช่วยใครซักคน
Zsolti

123

การแบ่งปันทรัพยากรข้ามแหล่งกำเนิด - CORS(คำขอ AKA Cross-Domain AJAX) เป็นปัญหาที่นักพัฒนาเว็บส่วนใหญ่อาจพบตามเบราว์เซอร์เดิม จำกัด นโยบายเบราว์เซอร์ จำกัด ไคลเอ็นต์ JavaScript ในแซนด์บ็อกซ์รักษาความปลอดภัยโดยปกติ JS ไม่สามารถสื่อสารโดยตรงกับเซิร์ฟเวอร์ระยะไกล จากโดเมนอื่น ในอดีตนักพัฒนาสร้างวิธีที่ยุ่งยากมากมายในการบรรลุการร้องขอทรัพยากรข้ามโดเมนส่วนใหญ่ใช้วิธี:

  1. ใช้ Flash / Silverlight หรือฝั่งเซิร์ฟเวอร์เป็น "พร็อกซี" เพื่อสื่อสารกับรีโมท
  2. JSON With Padding ( JSONP )
  3. ฝังเซิร์ฟเวอร์ระยะไกลใน iframe และการติดต่อสื่อสารผ่านส่วนหรือ window.name โปรดดูที่นี่

วิธีที่ยุ่งยากเหล่านั้นมีปัญหาบางอย่างมากขึ้นหรือน้อยลงตัวอย่างเช่น JSONP อาจส่งผลให้เกิดช่องโหว่ด้านความปลอดภัยหากผู้พัฒนาเพียงแค่ "eval" และ # 3 ด้านบนแม้ว่ามันจะใช้ได้ แต่โดเมนทั้งสองควรสร้างสัญญาที่เข้มงวดระหว่างกัน IMHO :)

W3C ได้แนะนำ Cross-Origin Resource Sharing (CORS) เป็นโซลูชันมาตรฐานเพื่อให้วิธีการที่ปลอดภัยยืดหยุ่นและเป็นวิธีมาตรฐานที่แนะนำในการแก้ปัญหานี้

กลไก

จากระดับสูงเราสามารถเห็นว่า CORS เป็นสัญญาระหว่างลูกค้า AJAX โทรจากโดเมน A และหน้าโฮสต์บนโดเมน B คำขอ / การตอบสนองข้ามแหล่งกำเนิดโดยทั่วไปจะเป็น:

ส่วนหัวคำขอ DomainA AJAX

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

ส่วนหัวการตอบสนอง DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

ส่วนสีฟ้าที่ฉันทำเครื่องหมายไว้ด้านบนคือข้อเท็จจริงของ kernal ส่วนหัวคำขอ "Origin" "ระบุตำแหน่งที่คำขอข้ามต้นกำเนิดหรือคำขอ preflight มีต้นกำเนิดมาจาก" ส่วนหัวตอบกลับ "Access-Control-Allow-Origin" ระบุว่าหน้านี้อนุญาตการร้องขอจากระยะไกล DomainA (หากค่าเป็น * หมายถึงอนุญาตการร้องขอระยะไกลจากโดเมนใด ๆ )

ดังที่ฉันได้กล่าวไว้ข้างต้น W3 แนะนำให้ใช้เบราว์เซอร์ " คำขอ preflight " ก่อนที่จะส่งคำขอ HTTP ข้ามแหล่งกำเนิดจริงโดยสังเขปมันเป็นOPTIONSคำขอHTTP :

OPTIONS DomainB.com/foo.aspx HTTP/1.1

หาก foo.aspx สนับสนุนคำกริยา HTTP ของ OPTIONS อาจส่งคืนการตอบกลับดังนี้:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

เฉพาะในกรณีที่คำตอบประกอบด้วย "Access-Control-Allow-Origin" และค่าของมันคือ "*" หรือมีโดเมนที่ส่งคำขอ CORS โดยการตอบสนองเบราว์เซอร์เงื่อนไข mandtory นี้จะส่งคำขอข้ามโดเมนจริงและแคชผลลัพธ์ ใน " Preflight-Result-Cache "

ฉัน blogged เกี่ยวกับ CORS สามปีที่ผ่านมา: AJAX Cross-Origin HTTP ร้องขอ


คำตอบนี้ทำให้ฉันรู้ว่าทำไมฉันถึงได้รับปัญหาโดยไม่ใช้หัวข้อนี้สำหรับคำขอ POST และ GET ฉันบังเอิญเปิดไฟล์ index.html จากดิสก์โดยตรงดังนั้น URL ที่ไคลเอ็นต์กำลังเข้าถึงบน node.js คิดว่าเป็น cross-domain ในขณะที่มันทำงานบน localhost การเข้าถึงผ่านทาง URL (เป็นหนึ่งมักจะทำ) "แก้ปัญหา" ของฉัน ...
LuqJensen

โดเมนในเครือข่ายภายนอกสามารถสื่อสารกับโดเมนบนเครือข่ายภายในได้หรือไม่
Si8

68

คำถามนั้นเก่าเกินไปที่จะตอบ แต่ฉันกำลังโพสต์สิ่งนี้ไว้เพื่ออ้างอิงในอนาคตกับคำถามนี้

จากบทความของ Mozilla Developer Network

ทรัพยากรสร้างการร้องขอ HTTP ข้ามแหล่งเมื่อร้องขอทรัพยากรจากโดเมนอื่นหรือพอร์ตที่ไม่ใช่ทรัพยากรแรกที่ให้บริการ

ป้อนคำอธิบายรูปภาพที่นี่

หน้า HTMLเสิร์ฟhttp://domain-a.comทำให้<img>คำขอ src http://domain-b.com/image.jpgสำหรับ
หลายหน้าบนเว็บทรัพยากรโหลดในวันนี้เช่นstylesheets CSS , ภาพและสคริปต์จากโดเมนแยกต่างหาก (ดังนั้นมันควรจะเป็นเย็น)

นโยบายแหล่งกำเนิดเดียวกัน

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

การแบ่งปันทรัพยากรข้ามแหล่งกำเนิด (CORS)

ในการปรับปรุงเว็บแอปพลิเคชันผู้พัฒนาขอให้ผู้ขายเบราว์เซอร์อนุญาตคำขอข้ามโดเมน

ทรัพยากรข้ามแหล่งที่ใช้ร่วมกัน ( ธ )กลไกให้เว็บเซิร์ฟเวอร์การควบคุมการเข้าถึงข้ามโดเมนซึ่งช่วยให้การรักษาความปลอดภัยข้ามโดเมนการถ่ายโอนข้อมูล
เบราว์เซอร์สมัยใหม่ใช้CORSในคอนเทนเนอร์ APIเช่นXMLHttpRequestหรือFetchเพื่อลดความเสี่ยงของการร้องขอ HTTP ข้ามต้นทาง

CORS ทำงานอย่างไร ( Access-Control-Allow-Originส่วนหัว)

Wikipedia :

มาตรฐาน CORS อธิบายส่วนหัว HTTP ใหม่ที่ให้เบราว์เซอร์และเซิร์ฟเวอร์วิธีการขอ URL ระยะไกลเฉพาะเมื่อได้รับอนุญาต

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

ตัวอย่าง

  1. เบราว์เซอร์ส่งOPTIONSคำขอพร้อมกับOrigin HTTPส่วนหัว

    ค่าของส่วนหัวนี้คือโดเมนที่ให้บริการหน้าหลัก เมื่อหน้าhttp://www.example.comพยายามเข้าถึงข้อมูลของผู้ใช้service.example.comส่วนหัวคำขอต่อไปนี้จะถูกส่งไปที่service.example.com:

    แหล่งกำเนิด: http://www.example.com

  2. เซิร์ฟเวอร์ที่service.example.comอาจตอบสนองด้วย:

    • Access-Control-Allow-Origin(ACAO) ส่วนหัวในการตอบสนองของมันแสดงให้เห็นว่าเว็บไซต์แหล่งกำเนิดจะได้รับอนุญาต
      ตัวอย่างเช่น:

      Access-Control-Allow-Origin: http://www.example.com

    • หน้าข้อผิดพลาดหากเซิร์ฟเวอร์ไม่อนุญาตการร้องขอข้ามจุดกำเนิด

    • Access-Control-Allow-Origin(ACAO) ส่วนหัวที่มีสัญลักษณ์ตัวแทนที่ช่วยให้โดเมนทั้งหมด:

      Access-Control-Allow-Origin: *


1
วิธีการตั้งค่าไม่มีใครได้รับอนุญาตให้ acees บางสิ่งเช่นAccess-Control-Allow-Origin:null
Subin Chalil

2
เมื่อฉันไม่ต้องการให้ใครเข้าถึงทรัพยากรของฉันผ่าน CORS ฉันควรตั้งค่าAccess-Control-Allow-Originอะไร ฉันหมายถึงการปฏิเสธAccess-Control-Allow-Origin: *
สุบินชาลิล

4
อย่าตั้งค่าอะไรเลยเพื่อจุดประสงค์นั้น
2560

23

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

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

บางครั้งคุณต้องทำงานข้ามโดเมนซึ่งเป็นที่ที่ CORS เข้ามา CORS ผ่อนคลายนโยบายต้นกำเนิดเดียวกันสำหรับ domainB.com โดยใช้ Access-Control-Allow-Originส่วนหัวเพื่อแสดงรายการโดเมนอื่น ๆ (domainA.com) ที่เชื่อถือได้ในการเรียกใช้ JavaScript ที่สามารถโต้ตอบกับ domainA ได้ ดอทคอม

เพื่อให้เข้าใจว่าโดเมนใดควรให้บริการส่วนหัว CORS ให้พิจารณาสิ่งนี้ คุณเยี่ยมชม spyware.com ซึ่งมี JavaScript บางตัวที่พยายามส่งคำขอข้ามโดเมนไปยัง mybank.com ควรขึ้นอยู่กับ mybank.com ไม่ใช่ที่เป็นอันตรายในการตัดสินใจว่าจะตั้งค่าส่วนหัว CORS ที่ผ่อนคลายนโยบายต้นกำเนิดเดียวกันซึ่งอนุญาตให้ JavaScript จาก spyware.com ทำงานร่วมกับมันหรือไม่ หาก malicous.com สามารถตั้งค่าส่วนหัว CORS ของตนเองเพื่อให้ JavaScript เข้าถึง mybank.com ของตนเองได้สิ่งนี้จะทำให้นโยบายแหล่งกำเนิดเดียวกันหมดสิ้น

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


1
ระบุวรรค 2 คุณมี siteA หรือไม่ siteB ย้อนหลังในย่อหน้า 3 ฉันอาจเข้าใจผิด แต่ย่อหน้าก่อนหน้าดูเหมือนจะบอกเป็นนัยถึงไซต์ของ A ที่ใช้งาน JS ในคำถาม
cellepo

11

1. ไคลเอนต์ดาวน์โหลดรหัส javascript MyCode.js จากhttp: // siteA - ที่มา

รหัสที่ไม่ดาวน์โหลด - แท็กสคริปต์ html ของคุณหรือ XHR จากจาวาสคริปต์หรืออะไรก็ตาม - มาจากสมมติว่าhttp: // siteZ และเมื่อเบราว์เซอร์ร้องขอ MyCode.js ก็จะส่งส่วนหัว Origin: ซึ่งบอกว่า "Origin: http: // siteZ " เพราะจะเห็นว่าคุณกำลังร้องขอ siteA และ siteZ! = siteA (คุณไม่สามารถหยุดหรือแทรกแซงสิ่งนี้ได้)

2. ส่วนหัวการตอบสนองของ MyCode.js มี Access-Control-Allow-Origin: http: // siteBซึ่งฉันคิดว่าหมายความว่า MyCode.js ได้รับอนุญาตให้ทำการอ้างอิงข้ามแหล่งที่มาไปยังเว็บไซต์ B

ไม่ หมายความว่าเฉพาะไซต์ B เท่านั้นที่ได้รับอนุญาตให้ทำตามคำขอนี้ ดังนั้นคำขอ MyCode.js ของคุณจาก siteZ จึงได้รับข้อผิดพลาดแทนและโดยทั่วไปแล้วเบราว์เซอร์จะไม่ให้อะไรคุณ แต่ถ้าคุณให้เซิร์ฟเวอร์คืน ACAO: siteZ แทนคุณจะได้รับ MyCode.js หรือถ้ามันส่ง '*' มันจะใช้งานได้มันจะให้ทุกคนเข้ามาหรือถ้าเซิร์ฟเวอร์ส่งสตริงจากส่วนหัว Origin: ... แต่ ... เพื่อความปลอดภัยถ้าคุณกลัวแฮ็กเกอร์ เซิร์ฟเวอร์ของคุณควรอนุญาตแหล่งกำเนิดในรายการโปรดที่ได้รับอนุญาตให้ทำการร้องขอเหล่านั้น

จากนั้น MyCode.js มาจาก siteA เมื่อทำการร้องขอไปยังไซต์ B พวกเขาทั้งหมดเป็นจุดกำเนิดข้ามเบราว์เซอร์จะส่ง Origin: siteA และ siteB ต้องรับไซต์ A ให้รับรู้ว่าอยู่ในรายการย่อของผู้ร้องขอที่อนุญาตและส่ง ACAO: siteA กลับมา เบราว์เซอร์เท่านั้นที่จะให้สคริปต์ของคุณได้รับผลลัพธ์ของคำขอเหล่านั้น


10

ใช้ReactและAxiosเข้าร่วมลิงค์พร็อกซีไปยัง URL และเพิ่มส่วนหัวดังแสดงด้านล่าง

https://cors-anywhere.herokuapp.com/ + Your API URL

เพียงแค่เพิ่มลิงค์พร็อกซีจะทำงานได้ แต่ก็ยังสามารถโยนข้อผิดพลาดสำหรับไม่มีการเข้าถึงอีกครั้ง ดังนั้นดีกว่าเพื่อเพิ่มส่วนหัวที่แสดงด้านล่าง

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

คำเตือน: ไม่ควรใช้ในการผลิต

นี่เป็นเพียงการแก้ไขด่วนหากคุณกำลังดิ้นรนกับสาเหตุที่คุณไม่สามารถรับคำตอบคุณสามารถใช้สิ่งนี้ได้ แต่อีกครั้งมันไม่ใช่คำตอบที่ดีที่สุดสำหรับการผลิต

มีหลาย downvotes และเหมาะสมแล้วฉันควรจะเพิ่มคำเตือนเมื่อนานมาแล้ว


19
โปรดอย่าทำเช่นนี้ การใช้ลิงค์พร็อกซี่ก็เหมือนกับการมอบคุกกี้ผู้ใช้ให้กับคนกลาง ควรเป็น IMHO ที่ผิดกฎหมาย
anthonymonori

มันมีประโยชน์สำหรับฉัน! ยกเว้นแทนที่จะใช้ * (ซึ่งมีปัญหาด้านความปลอดภัย) ฉัน จำกัด การควบคุมการเข้าถึงเฉพาะที่อยู่ที่ฉันใช้เพื่อเรียนรู้กับ ... ในกรณีของฉัน ' reqres.in/api/register '
C-Note187

9

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

open -a Google\ Chrome --args --disable-web-security --user-data-dir

9

หากคุณใช้ PHP ลองเพิ่มรหัสต่อไปนี้ที่จุดเริ่มต้นของไฟล์ php:

หากคุณใช้ localhost ลองสิ่งนี้:

header("Access-Control-Allow-Origin: *");

หากคุณใช้โดเมนภายนอกเช่นเซิร์ฟเวอร์ลองสิ่งนี้:

header("Access-Control-Allow-Origin: http://www.website.com");

7

ฉันทำงานกับ express 4 และ node 7.4 และ angular ฉันมีปัญหาเดียวกันฉันช่วยสิ่งนี้:
a) ฝั่งเซิร์ฟเวอร์: ในไฟล์ app.js ฉันให้ส่วนหัวในการตอบสนองทั้งหมดเช่น:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

นี้จะต้องมีก่อนเราเตอร์ทั้งหมด
ฉันเห็นส่วนหัวนี้เพิ่มจำนวนมาก:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

แต่ฉันไม่ต้องการนั้น
b) ฝั่งไคลเอ็นต์: ในการส่ง ajax คุณต้องเพิ่ม: "withCredentials: true" เช่น:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

โชคดี.


res.header('Access-Control-Allow-Origin', req.headers.origin);เหมือนกับres.header('Access-Control-Allow-Origin', '*');
The Aelfinn

4

สำหรับการแบ่งปันข้ามกำเนิดให้ตั้งค่าส่วนหัว: 'Access-Control-Allow-Origin':'*';

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

โหนด: app.use('Access-Control-Allow-Origin':'*');

วิธีนี้จะช่วยให้สามารถแบ่งปันเนื้อหาสำหรับโดเมนที่ต่างกัน


4

ใน Python ฉันใช้Flask-CORSห้องสมุดอย่างประสบความสำเร็จ มันทำให้การจัดการกับ CORS ง่ายและไม่เจ็บปวด ฉันเพิ่มรหัสบางอย่างจากเอกสารของห้องสมุดด้านล่าง

การติดตั้ง:

$ pip install -U flask-cors

ตัวอย่างง่ายๆที่อนุญาตให้ CORS สำหรับโดเมนทั้งหมดในทุกเส้นทาง:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

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

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


4

จากประสบการณ์ของฉันเองมันยากที่จะหาคำอธิบายง่ายๆว่าทำไม CORS ถึงเป็นข้อกังวล

เมื่อคุณเข้าใจว่าทำไมมันถึงอยู่ที่นั่นส่วนหัวและการสนทนาจะชัดเจนยิ่งขึ้น ฉันจะให้มันยิงในไม่กี่บรรทัด


มันคือทั้งหมดที่เกี่ยวกับคุกกี้ คุกกี้ถูกเก็บไว้ในไคลเอนต์โดยโดเมนของพวกเขา

เรื่องราวตัวอย่างเช่น: yourbank.comบนคอมพิวเตอร์ของคุณมีคุกกี้สำหรับ บางทีเซสชันของคุณอยู่ในนั้น

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

yourbank.comคุณเข้าสู่ระบบในเบราว์เซอร์ของคุณเพื่อ คุณขอดูบัญชีทั้งหมดของคุณ yourbank.comรับกองคุกกี้และส่งการตอบกลับ (บัญชีของคุณ)

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

malicious.comคุณเรียกดู yourbank.comที่เป็นอันตรายทำให้พวงของการร้องขอไปยังธนาคารที่แตกต่างกันรวมทั้ง

เนื่องจากคุกกี้ได้รับการตรวจสอบตามที่คาดไว้เซิร์ฟเวอร์จะอนุมัติการตอบกลับ

คุกกี้เหล่านั้นได้รับการรวบรวมและส่งไปพร้อม - และตอนนี้มีการตอบสนองจากmalicious.comyourbank

Yikes


ดังนั้นคำถามและคำตอบบางอย่างก็ชัดเจน

  • "ทำไมเราไม่บล็อกเบราว์เซอร์ไม่ให้ทำเช่นนั้น?" อ๋อ ธ
  • "เราจะไปรอบ ๆ มันได้อย่างไร" ให้เซิร์ฟเวอร์แจ้งคำขอว่า CORS ตกลง

3

เพียงวางรหัสต่อไปนี้ในไฟล์ web.config ของคุณ

สังเกตว่าคุณต้องวางรหัสต่อไปนี้ภายใต้<system.webServer>แท็ก

    <httpProtocol>  
    <customHeaders>  
     <add name="Access-Control-Allow-Origin" value="*" />  
     <add name="Access-Control-Allow-Headers" value="Content-Type" />  
     <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
    </customHeaders>  
  </httpProtocol>  

0

ส่วนหัวการตอบสนองการเข้าถึงการควบคุมอนุญาตให้กำเนิดบ่งชี้ว่าการตอบสนองสามารถใช้ร่วมกันกับรหัสการร้องขอจากต้นกำเนิดที่กำหนด

Header type Response       header
Forbidden header name      no

การตอบสนองที่บอกให้เบราว์เซอร์อนุญาตให้ใช้รหัสจากจุดเริ่มต้นใด ๆ ในการเข้าถึงทรัพยากรจะรวมถึงสิ่งต่อไปนี้:

Access-Control-Allow-Origin: *

สำหรับข้อมูลเพิ่มเติมเยี่ยมชมที่นี่ ....


0

Nginx และ Appache

นอกเหนือจากคำตอบของ apsillersแล้วฉันต้องการเพิ่มวิกิกราฟซึ่งแสดงให้เห็นว่าคำขอนั้นเรียบง่ายหรือไม่

ป้อนคำอธิบายภาพที่นี่

สำหรับคำของ่าย ๆ (เช่นรูปภาพ hotlinking ) คุณไม่จำเป็นต้องเปลี่ยนไฟล์การกำหนดค่าเซิร์ฟเวอร์ แต่คุณสามารถเพิ่มส่วนหัวในแอปพลิเคชัน (โฮสต์บนเซิร์ฟเวอร์เช่นใน php) เช่น Melvin Guerrero พูดถึงคำตอบของเขา- แต่จำไว้ : ส่วนหัว cors ในเซิร์ฟเวอร์ของคุณ (config) และในเวลาเดียวกันคุณอนุญาตให้ cors ง่าย ๆ ในแอปพลิเคชัน (เช่น php) สิ่งนี้จะไม่ทำงานเลย

และนี่คือการกำหนดค่าสำหรับเซิร์ฟเวอร์ยอดนิยมสองตัว

  • เปิดCORS บน Nginx ( nginx.confไฟล์)

  • เปิดCORS บน Appache ( .htaccessไฟล์)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.