2010-03-05 9 views
86

Non ho dormito abbastanza o cosa? Questo seguente codicePerché canvas.toDataURL() genera un'eccezione di sicurezza?

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

sta gettando questo errore:

SECURITY_ERR: DOM Exception 18 

Non c'è modo questo non dovrebbe funzionare! Qualcuno può spiegarlo, per favore?

+0

Vedere qui per una soluzione: [Come utilizzare canvas.toDataURL() per ottenere base64 dell'immagine in Adobe AIR?] (Http://stackoverflow.com/q/3672332) –

+2

Questa soluzione non sembra utile per le persone che non usano Adobe AIR. – ObscureRobot

risposta

67

Nel specs si dice:

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.

Se l'immagine è in arrivo da un altro server non credo che si può usare toDataURL()

+0

Ed eccolo, –

+0

, grazie mille! come Mike R. Non riesco a immaginare come possa essere correlato alla sicurezza! :) – pop850

+6

Se un utente malintenzionato è in grado di indovinare il nome di un'immagine che si trova in un sito privato, sarebbe in grado di ottenerne una copia dipingendo su una tela e inviando la nuova immagine al suo sito. La principale restrizione dal mio punto di vista è evitare di disegnare il contenuto di un altro sito, ma la sicurezza è troppo complessa in quanto l'attaccante può trovare un buco in qualsiasi sito inatteso. – AlfonsoML

1

Non puoi inserire spazi nel vostro ID

Aggiornamento

La mia ipotesi è che l'immagine si trova su un server diverso da quello in cui si sta eseguendo lo script. Sono stato in grado di duplicare il tuo errore durante l'esecuzione sulla mia pagina, ma ha funzionato bene nel momento in cui ho usato un'immagine ospitata nello stesso dominio. Quindi è legato alla sicurezza - metti l'immagine sul tuo sito. Qualcuno sa perché questo è il caso?

+0

Ho cambiato e testato, ma ho ottenuto lo stesso errore ... – pop850

+0

@ pop850: vedi modifica – Matchu

13

sembra che ci sia un modo per evitare che se l'immagine di hosting in grado di fornire i seguenti intestazioni HTTP per le risorse di immagini e browser supporta CORS:

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

si afferma qui: http://www.w3.org/TR/cors/#use-cases

+1

access-control-allow-credentials: true non funziona con access-control-allow-origin: *. Quando il primo è impostato, quest'ultimo deve avere un valore di origine, non un valore jolly da https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS –

16

Se l'immagine è ospitata su un host che imposta Access-Control-Allow-Origin o Access-Control-Allow-Credentials, è possibile utilizzare Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.

L'altra opzione è che il server abbia un endpoint che recupera e serve un'immagine. (ad esempio http://your_host/endpoint?url=URL) Lo svantaggio di questo approccio è la latenza e il recupero teoricamente non necessario.

Se ci sono altre soluzioni alternative, sarei interessato a sentirle.

+0

Ciao, l'ho fatto solo, ho accesso- Control-Allow-Origin: * sulle immagini, ho crossorigin = 'anonymous', quindi dipingo l'immagine su tela, poi chiamo suDataUrl e sto ancora ottenendo SECURITY_ERR: DOM Exception 18 – skrat

+0

Bene, usa setAttribute invece di img.crossorigin – skrat

17

Impostazione attributo croce origine sugli oggetti immagine ha lavorato per me (stavo usando 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'; 

per coloro che utilizzano fabricjs, ecco come patchare 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

Grazie, funziona per me in Chrome. Non sto usando fabric.js anche se – Philip007

+0

io uso fabricjs ma non ho potuto risolverlo. Come faresti questo con questo codice? 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', sinistra: 0, top : 0 }); }; bg_img.src = img_url; } } – HOY

+0

Funziona anche in Firefox. – vanowm

2

ho avuto la lo stesso problema e tutte le immagini sono ospitate nello stesso dominio ... Quindi, se qualcuno sta avendo lo stesso problema, ecco come ho risolto:

Avevo due pulsanti: uno per generare la tela e un'altra per generare l'immagine dalla tela. Ha funzionato solo per me, e mi dispiace di non sapere perché, quando ho scritto tutto il codice sul primo pulsante. Quindi quando clicco, generano la tela e l'immagine allo stesso tempo ...

Ho sempre questo problema di sicurezza quando i codici erano su funzioni diverse ...=/

0

Se stai semplicemente disegnando alcune immagini su una tela, assicurati di caricare le immagini dallo stesso dominio.

www.example.com è diverso da example.com

modo da assicurarsi che le immagini e l'URL che avete nella vostra barra degli indirizzi sono gli stessi, www o no.

1

sono stato in grado di farlo funzionare con questo:

Write questo sulla prima linea della vostra .htaccess sul server di origine

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

Poi, quando la creazione di un elemento <img>, farlo nel seguente modo:

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

Finalmente ho trovato la soluzione. Solo bisogno aggiungere il crossOrigin come terzo param in fromURL func

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

Mi ha davvero aiutato con Fabric JS, grazie! – hcabral

0

sto usando fabric.js e potrebbe risolvere questo utilizzando toDatalessJSON invece di toDataURL:

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

Edit: Nevermind. Ciò comporta che l'immagine di sfondo venga esportata in JPG, senza il disegno in alto, quindi non era del tutto utile, dopotutto.

Problemi correlati