โดยทั่วไป ทีมจะมีชื่อโดเมนพิเศษสำหรับวางทรัพยากรแบบคงที่ เช่น Tencent คือ gtimg.com, Baidu คือ bdimg.com หรือหลายๆ ทีมใช้บริการ Tencent Cloud หรือ Alibaba Cloud
ชื่อโดเมนของเพจหลักมักจะแตกต่างกัน เมื่อจำเป็นต้องดำเนินการ getImageData() หรือ toDataURL() บนอิมเมจแคนวาส ปัญหาข้ามโดเมนจะเกิดขึ้น และมีปัญหาข้ามโดเมนมากกว่าหนึ่งระดับ
ขั้นแรก ในขั้นตอนแรก เซิร์ฟเวอร์รูปภาพจำเป็นต้องกำหนดค่าข้อมูล Access-Control-Allow-Origin เช่น:
ตัวอย่างเช่น PHP เพิ่มข้อมูลส่วนหัวการตอบกลับ และไวด์การ์ด * ระบุว่าอนุญาตให้ใช้ชื่อโดเมนใดก็ได้:
ส่วนหัว (Access-Control-Allow-Origin: *);
หรือระบุชื่อโดเมน:
ส่วนหัว (Access-Control-Allow-Origin: www.zhangxinxu.com);
ณ จุดนี้ เบราว์เซอร์ Chrome จะไม่มีข้อความแสดงข้อผิดพลาดที่เกี่ยวข้องกับ Access-Control-Allow-Origin อีกต่อไป แต่จะมีข้อความแสดงข้อผิดพลาดข้ามโดเมนอื่นๆ
2. Canvas picture getImageData ปัญหาข้ามโดเมนข้ามต้นทางสำหรับรูปภาพข้ามโดเมน ตราบใดที่สามารถแสดงได้ตามปกติบนหน้าเว็บ ก็สามารถวาดได้โดยใช้ DrawImage() API ของ Canvas แต่ถ้าคุณต้องการก้าวไปอีกขั้นและรับข้อมูลพิกเซลที่สมบูรณ์ของรูปภาพโดยใช้เมธอด getImageData() คุณอาจจะทำให้เกิดข้อผิดพลาดได้
ตัวอย่างเช่น ใช้โค้ดต่อไปนี้เพื่อรับข้อมูลรูปภาพประจำตัวของคุณเองบน GitHub:
var canvas = document.createElement('canvas');var context = canvas.getContext('2d');var img = new Image();img.onload = function () { context.drawImage(this, 0, 0) ; context.getImageData(0, 0, this.width, this.height);};img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
ผลลัพธ์คือข้อผิดพลาดต่อไปนี้แสดงใต้เบราว์เซอร์ Chrome:
Uncaught DOMException: ไม่สามารถดำเนินการ 'getImageData ' บน 'CanvasRenderingContext2D ': ผืนผ้าใบได้รับความเสียหายจากข้อมูลข้ามแหล่งกำเนิด
ข้อผิดพลาดของเบราว์เซอร์ Firefox คือ:
SecurityError: การดำเนินการไม่ปลอดภัย
หากใช้เมธอด canvas.toDataURL() จะรายงาน:
ไม่สามารถดำเนินการ 'toDataURL' บน 'HTMLCanvasElement': ผืนผ้าใบที่มีมลทินอาจไม่ถูกส่งออก
จริงๆ แล้วเหตุผลเหมือนกันคือเกิดจากการข้ามโดเมน
มีวิธีแก้ไขปัญหานี้หรือไม่?
คุณสามารถลองใช้แอตทริบิวต์ crossOrigin
3. แอตทริบิวต์ HTML crossOrigin แก้ปัญหาข้ามโดเมนของทรัพยากรใน HTML5 องค์ประกอบบางอย่างมีแอตทริบิวต์ที่รองรับ CORS (การแบ่งปันทรัพยากรข้ามต้นทาง) (การแบ่งปันทรัพยากรข้ามต้นทาง) องค์ประกอบเหล่านี้ประกอบด้วย <img>, <video>, <script> ฯลฯ และชื่อแอตทริบิวต์ที่ให้ไว้คือ แอตทริบิวต์ crossOrigin
ดังนั้นปัญหาข้ามโดเมนข้างต้นสามารถจัดการได้ดังนี้:
var canvas = document.createElement('canvas');var context = canvas.getContext('2d');var img = new Image();img.crossOrigin = '';img.onload = function () { context.drawImage (นี่, 0, 0); context.getImageData(0, 0, this.width, this.height);};img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
เพียงเพิ่ม img.crossOrigin = '' แม้ว่าโค้ด JS ที่นี่จะตั้งค่าสตริงว่าง แต่ค่าแอตทริบิวต์จริงที่ใช้งานได้นั้นจะไม่ระบุชื่อ
crossOrigin สามารถมีค่าได้ 2 ค่าต่อไปนี้:
คำหลัก | คำนิยาม |
---|---|
ไม่ระบุชื่อ | คำขอทรัพยากรข้ามต้นทางสำหรับองค์ประกอบไม่จำเป็นต้องตั้งค่าสถานะข้อมูลรับรอง |
ข้อมูลประจำตัวการใช้งาน | คำขอทรัพยากรข้ามโดเมนสำหรับองค์ประกอบจำเป็นต้องมีการตั้งค่าสถานะข้อมูลรับรอง ซึ่งหมายความว่าจำเป็นต้องมีข้อมูลรับรองสำหรับคำขอ |
ในบรรดาค่าเหล่านี้ ตราบใดที่ค่าแอตทริบิวต์ของ crossOrigin ไม่ใช่ use-credentials ทุกอย่างจะถูกแยกวิเคราะห์เป็นแบบไม่ระบุชื่อ รวมถึงสตริงว่าง รวมถึงอักขระ เช่น 'abc'
ตัวอย่างเช่น:
img.crossOrigin = 'abc';console.log(img.crossOrigin); // ผลลัพธ์คือ 'ไม่เปิดเผยตัวตน'
สิ่งที่ควรทราบอีกประการหนึ่งก็คือ แม้ว่าจะไม่มีแอตทริบิวต์ crossOrigin และการตั้งค่า crossOrigin=use-credentials จะรายงานข้อผิดพลาดข้ามโดเมนตามค่าเริ่มต้น แต่ก็มีความแตกต่างกันอย่างมากระหว่างทั้งสอง
ความเข้ากันได้ของ CrossOriginเบราว์เซอร์ IE11+ (IE Edge), Safari, Chrome และ Firefox ทั้งหมดรองรับ IE9 และ IE10 จะรายงานข้อผิดพลาดด้านความปลอดภัย ดังที่แสดงในภาพหน้าจอด้านล่าง:
4. เหตุใดแอตทริบิวต์ crossOrigin จึงสามารถแก้ปัญหาทรัพยากรข้ามโดเมนได้crossOrigin=anonymous แทนที่จะแจ้งให้เซิร์ฟเวอร์อื่นทราบ คุณไม่จำเป็นต้องนำข้อมูลที่ไม่ระบุชื่อมาด้วย ตัวอย่างเช่นคุกกี้ ดังนั้น เบราว์เซอร์ปัจจุบันจึงปลอดภัยอย่างแน่นอน
มันเหมือนกับว่าคุณอยากไปบ้านใครสักคนเพื่อไปซื้อเสื้อผ้า crossOrigin=anonymous นั้นแตกต่างจากการบอกคนอื่นว่าฉันต้องการแค่เสื้อผ้าเท่านั้นและไม่มีอะไรอื่นอีก หากคุณไม่บอกอีกฝ่ายอาจใส่อุปกรณ์ฟังหรือสิ่งของบางอย่างไว้ในเสื้อผ้า ซึ่งจะไม่ปลอดภัยและเบราว์เซอร์จะบล็อกอุปกรณ์นั้น
5. ฉันควรทำอย่างไรหากเบราว์เซอร์ IE10 ไม่รองรับ crossOriginเมื่อเราขอรูปภาพ เราไม่ได้ใช้ new Image() โดยตรง แต่ใช้ ajax และเมธอด URL.createObjectURL() เพื่อบันทึกประเทศ
รหัสมีดังนี้:
var xhr = new XMLHttpRequest();xhr.onload = function () { var url = URL.createObjectURL(this.response); var img = new Image(); img.onload = function () { // ณ จุดนี้คุณ คุณสามารถใช้ Canvas เพื่อทำอะไรก็ได้ที่คุณต้องการด้วย img // ... code ... // อย่าลืมปล่อยหน่วยความจำหลังจากใช้รูปภาพ URL.revoidObjectURL(url); img.src = url;};xhr.open('GET', url, true);xhr.responseType = 'blob';xhr.send();
วิธีการนี้ไม่เพียงใช้ได้กับเบราว์เซอร์ IE10 เท่านั้น แต่ยังรองรับเบราว์เซอร์ทั้งหมดที่รองรับ CrossOrigin ในตอนแรกอีกด้วย
ต้องการเพียงคำขอ ajax อีกหนึ่งคำขอเท่านั้น ซึ่งก็ไม่เป็นไร!
ตามแนวทางปฏิบัติ ภายใต้เบราว์เซอร์ IE หากรูปภาพที่ร้องขอมีขนาดใหญ่เกินไป ไม่กี่พันพิกเซล รูปภาพจะไม่สามารถโหลดได้ ฉันเดาว่ามันเกินขีดจำกัดขนาดหยด
6. บทสรุปฉันได้เรียนรู้ประสบการณ์เล็กๆ น้อยๆ ในที่ทำงานเมื่อเร็ว ๆ นี้ ฉันหวังว่าจะสามารถช่วยเพื่อน ๆ ที่ประสบปัญหาคล้ายกันได้ ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network