2010-03-05 5 views
86

Разве я не спал или что? Это следующий кодПочему canvas.toDataURL() выдает исключение безопасности?

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")); 
} 

бросает эту ошибку:

SECURITY_ERR: DOM Exception 18 

Там нет никакого способа это не должно работать! Может кто-нибудь объяснить это, пожалуйста?

+0

См. Здесь для решения: [Как использовать canvas.toDataURL(), чтобы получить base64 изображения в Adobe AIR?] (Http://stackoverflow.com/q/3672332) –

+2

Это решение не кажется полезным для люди, не использующие Adobe AIR. – ObscureRobot

ответ

67

В specs он говорит:

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.

Если изображение идет с другого сервера, я не думаю, что вы можете использовать toDataURL()

+0

И вот это –

+0

большое спасибо! как Майк Р. Я не могу представить, как это может быть связано с безопасностью! :) – pop850

+6

Если злоумышленник может угадать имя изображения, которое у вас есть на частном сайте, он сможет получить его копию, нарисовав на холсте и отправив новое изображение на свой сайт. Основное ограничение с моей точки зрения заключается в том, чтобы избежать рисования содержимого другого сайта, но безопасность слишком сложна, так как злоумышленник может найти дыру на любом неожиданном сайте. – AlfonsoML

1

Вы не можете вставлять пробелы в вашем ID

Update

Я думаю, что изображение находится на другом сервере, чем где вы выполнение сценария. Я смог дублировать вашу ошибку при запуске на моей собственной странице, но она отлично работала в тот момент, когда я использовал изображение, размещенное в том же домене. Так что это связано с безопасностью - поместите изображение на свой сайт. Кто-нибудь знает, почему это так?

+0

Я изменил это и протестировал его, но получил ту же ошибку ... – pop850

+0

@ pop850: см. Править – Matchu

13

Кажется, есть способ, чтобы предотвратить это, если изображение хостинг в состоянии предоставить следующие заголовки HTTP для графических ресурсов и браузер поддерживает CORS:

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

Это изложено здесь: http://www.w3.org/TR/cors/#use-cases

+1

access-control-allow-credentials: true не будет работать с доступом-control-allow-origin: *. Когда первое установлено, последнее должно иметь значение начала, а не значение подстановки из https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS –

16

Если изображение размещено на хосте, который устанавливает любой из Access-Control-Allow-Origin или Access-Control-Allow-Credentials, вы можете использовать Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.

Ваш другой вариант - для вашего сервера иметь конечную точку, которая извлекает и обслуживает изображение. (например, http://your_host/endpoint?url=URL) Недостатком этого подхода является латентность и теоретически ненужная выборка.

Если есть более альтернативные решения, мне было бы интересно услышать о них.

+0

Привет, я сделал именно это, у меня есть Access- Control-Allow-Origin: * на изображениях, у меня есть crossorigin = 'anonymous', затем я рисую изображение на холсте, затем я вызываю toDataUrl, и я все еще получаю SECURITY_ERR: DOM Exception 18 – skrat

+0

Хорошо, вместо этого используйте setAttribute img.crossorigin – skrat

17

Установка перекрестное атрибут происхождения на объекты изображения, работал для меня (я использовал 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'; 

Для тех, кто использует fabricjs, вот как пропатчить 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

Спасибо, он работает для меня в Chrome. Я не использую fabric.js, хотя – Philip007

+0

Я использую fabricjs, но не смог его решить. Как вы это сделаете с помощью этого кода? function wtd_load_bg_image (img_url) { if (img_url) { var bg_img = new Изображение(); bg_img.onload = функция() { canvasObj.setBackgroundImage (bg_img.src, canvasObj.renderAll.bind (canvasObj), { originX: 'левый', originY: 'сверху', слева: 0, сверху : 0 }); }; bg_img.src = img_url; } } – HOY

+0

Работает также в Firefox. – vanowm

2

Я имел та же проблема, и все изображения размещаются в одном домене ... Итак, если у кого-то такая же проблема, вот как я решил:

У меня было две кнопки: одна для генерации холст и еще один, чтобы сгенерировать изображение с холста. Это работало только для меня, и жаль, что я не знаю, почему, когда я написал весь код на первой кнопке. Поэтому, когда я нажимаю, он генерирует холст и изображение одновременно ...

У меня всегда есть эта проблема с безопасностью, когда коды были на разных функциях ...=/

0

Если вы просто рисуете некоторые изображения на холсте, убедитесь, что вы загружаете изображения из одного домена.

www.example.com отличается example.com

Поэтому убедитесь, что ваши изображения и URL вас в адресной строке одинаковы, WWW или нет.

1

я был в состоянии сделать его работу с помощью этого:

Записать это на первой строке .htaccess на исходном сервере

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

Тогда при создании <img> элемент, сделать это следующим образом:

// 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

И наконец, я нашел решение. Просто нужно добавить crossOrigin в качестве третьих паров в fromURL FUNC

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

Действительно помог мне с Fabric JS, спасибо! – hcabral

0

Я использую fabric.js и могу решить эту проблему с помощью toDatalessJSON вместо toDataURL:

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

Edit: Nevermind. Это приводит к тому, что только фоновое изображение экспортируется в JPG, без рисунка сверху, так что это не совсем полезно.