2010-03-05 44 views
86

Tôi không ngủ đủ giấc hay sao? Mã này sauTại sao canvas.toDataURL() ném một ngoại lệ bảo mật?

var frame=document.getElementById("viewer"); 
frame.width=100; 
frame.height=100; 

var ctx=frame.getContext("2d"); 
var img=new Image(); 
img.src="http://www.ansearch.com/images/interface/item/small/image.png" 

img.onload=function() { 
    // draw image 
    ctx.drawImage(img, 0, 0) 

    // Here's where the error happens: 
    window.open(frame.toDataURL("image/png")); 
} 

được ném lỗi này:

SECURITY_ERR: DOM Exception 18 

Không có cách nào điều này không nên làm việc! Bất cứ ai có thể giải thích điều này, xin vui lòng?

+0

Xem tại đây để biết giải pháp: [Cách sử dụng canvas.toDataURL() để lấy base64 của hình ảnh trong Adobe AIR?] (Http://stackoverflow.com/q/3672332) –

+2

Giải pháp đó dường như không hữu ích đối với mọi người không sử dụng Adobe AIR. – ObscureRobot

Trả lời

67

Trong specs nó nói:

Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.

Nếu hình ảnh đến từ máy chủ khác tôi không nghĩ rằng bạn có thể sử dụng toDataURL()

+0

Và có nó là –

+0

cảm ơn rất nhiều! như Mike R. Tôi không thể tưởng tượng được điều này có thể liên quan đến bảo mật như thế nào! :) – pop850

+6

Nếu kẻ tấn công có thể đoán tên của một bức ảnh mà bạn có trong một trang web riêng tư, anh ta sẽ có thể nhận được một bản sao của nó bằng cách vẽ trên một khung và gửi hình ảnh mới đến trang web của mình. Hạn chế chính từ quan điểm của tôi là tránh vẽ nội dung của một trang web khác, nhưng bảo mật quá phức tạp vì kẻ tấn công có thể tìm thấy lỗ hổng trong bất kỳ trang web bất ngờ nào. – AlfonsoML

1

Bạn không thể đặt dấu cách trong ID của bạn

Cập nhật

Tôi đoán là hình ảnh đó là trên một máy chủ khác với nơi bạn đang thực hiện kịch bản. Tôi đã có thể sao chép lỗi của bạn khi chạy nó trên trang của riêng tôi, nhưng nó làm việc tốt thời điểm tôi đã sử dụng một hình ảnh được lưu trữ trên cùng một tên miền. Vì vậy, nó liên quan đến an ninh - đưa hình ảnh trên trang web của bạn. Bất cứ ai biết tại sao đây là trường hợp?

+0

Tôi đã thay đổi điều này và thử nghiệm nó, nhưng có cùng một lỗi ... – pop850

+0

@ pop850: xem chỉnh sửa – Matchu

13

Có vẻ có một cách để ngăn chặn điều đó nếu hình ảnh lưu trữ có thể cung cấp các tiêu đề HTTP sau cho các nguồn tài nguyên hình ảnh và trình duyệt hỗ trợ CORS:

access-control-allow-origin: * 
access-control-allow-credentials: true

Đó là tuyên bố ở đây: http://www.w3.org/TR/cors/#use-cases

+1

quyền truy cập-kiểm soát-cho phép-thông tin xác thực: true sẽ không hoạt động với quyền truy cập-cho phép-cho phép xuất xứ: *. Khi giá trị cũ được đặt, giá trị sau phải có giá trị gốc, không phải giá trị ký tự đại diện từ https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS –

16

Nếu hình ảnh được lưu trữ trên một máy chủ đặt Access-Control-Allow-Origin hoặc Access-Control-Allow-Credentials, bạn có thể sử dụng Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.

Tùy chọn khác của bạn là để máy chủ của bạn có điểm cuối tìm nạp và phục vụ hình ảnh. (ví dụ: http://your_host/endpoint?url=URL) Nhược điểm của phương pháp đó là thời gian chờ và tìm nạp không cần thiết về mặt lý thuyết.

Nếu có nhiều giải pháp thay thế, tôi muốn được nghe về chúng.

+0

Xin chào, tôi đã làm điều đó, tôi có quyền truy cập- Control-Allow-Origin: * trên hình ảnh, tôi có crossorigin = 'anonymous', sau đó tôi vẽ hình ảnh trên canvas, sau đó tôi gọi toDataUrl và tôi vẫn nhận được SECURITY_ERR: DOM Exception 18 – skrat

+0

Được rồi, hãy sử dụng setAttribute thay thế của img.crossorigin – skrat

17

Thiết thuộc tính gốc chéo trên các đối tượng hình ảnh làm việc cho tôi (tôi đã sử dụng fabricjs)

var c = document.createElement("img"); 
    c.onload=function(){ 
     // add the image to canvas or whatnot 
     c=c.onload=null 
    }; 
    c.setAttribute('crossOrigin','anonymous'); 
    c.src='http://google.com/cat.png'; 

Đối với những người sử dụng fabricjs, dưới đây là cách để vá Image.fromUrl

// patch fabric for cross domain image jazz 
fabric.Image.fromURL=function(d,f,e){ 
    var c=fabric.document.createElement("img"); 
    c.onload=function(){ 
     if(f){f(new fabric.Image(c,e))} 
     c=c.onload=null 
    }; 
    c.setAttribute('crossOrigin','anonymous'); 
    c.src=d; 
}; 
+0

Cảm ơn, nó hoạt động với tôi trong Chrome. Tôi không sử dụng fabric.js mặc dù – Philip007

+0

Tôi sử dụng fabricj nhưng không thể giải quyết được. Làm thế nào bạn sẽ làm điều này với mã này? function wtd_load_bg_image (img_url) { if (img_url) { var bg_img = new Image(); bg_img.onload = function() { canvasObj.setBackgroundImage (bg_img.src, canvasObj.renderAll.bind (canvasObj), { originX: 'left', originY: 'top', trái: 0, đầu : 0 }); }; bg_img.src = img_url; } } – HOY

+0

Hoạt động trên Firefox. – vanowm

2

tôi đã có cùng một vấn đề và tất cả các hình ảnh được lưu trữ trong cùng một tên miền ... Vì vậy, nếu ai đó có cùng một vấn đề, dưới đây là cách tôi đã giải quyết:

Tôi có hai nút: một để tạo canvas và một ảnh khác để tạo hình ảnh từ canvas. Nó chỉ làm việc cho tôi, và xin lỗi vì tôi không biết tại sao, khi tôi viết tất cả các mã trên nút đầu tiên. Vì vậy, khi tôi nhấp vào nó sẽ tạo canvas và hình ảnh cùng một lúc ...

Tôi luôn gặp sự cố bảo mật này khi mã ở các chức năng khác nhau ...=/

0

Nếu bạn chỉ vẽ một số hình ảnh trên canvas, hãy đảm bảo bạn đang tải hình ảnh từ cùng một tên miền.

www.example.com là khác nhau để example.com

Vì vậy, hãy chắc chắn hình ảnh của bạn và các url mà bạn có trong thanh địa chỉ của bạn đều giống nhau, www hay không.

1

tôi đã có thể làm cho nó hoạt sử dụng này:

Viết này trên dòng đầu tiên của .htaccess của bạn trên máy chủ nguồn của bạn

Header add Access-Control-Allow-Origin "*" 

Sau đó, khi tạo một yếu tố <img>, làm điều đó như sau:

// jQuery 
var img = $('<img src="http://your_server/img.png" crossOrigin="anonymous">')[0] 

// or pure 
var img = document.createElement('img'); 
img.src='http://your_server/img.png'; 
img.setAttribute('crossOrigin','anonymous'); 
2

Cuối cùng tôi đã tìm ra giải pháp. Chỉ cần thêm crossOrigin như param thứ ba trong fromURL func

fabric.Image.fromURL(imageUrl, function (image) { 
      //your logic 
    }, { crossOrigin: "Anonymous" }); 
+0

Thực sự đã giúp tôi với Fabric JS, cảm ơn! – hcabral

0

Tôi đang sử dụng fabric.js và có thể giải quyết điều này bằng cách sử dụng toDatalessJSON thay vì toDataURL:

canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src 

Edit: Nevermind. Điều này dẫn đến hình ảnh nền chỉ được xuất sang JPG, mà không có bản vẽ ở phía trên để nó không hoàn toàn hữu ích sau khi tất cả.

Các vấn đề liên quan