webentwicklung-frage-antwort-db.com.de

Warum löst canvas.toDataURL () eine Sicherheitsausnahme aus?

Habe ich nicht genug geschlafen oder was? Dieser folgende Code

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

wirft diesen Fehler: 

SECURITY_ERR: DOM Exception 18

Das sollte auf keinen Fall funktionieren! Kann das bitte jemand erklären?

87
pop850

In den specs heißt es:

Wann immer die toDataURL () -Methode eines Canvas-Element, dessen Origin-clean-Flag auf false gesetzt ist, wird die Methode .__ aufgerufen. muss eine SECURITY_ERR-Ausnahme auslösen.

Wenn das Image von einem anderen Server kommt, glaube ich nicht, dass Sie toDataURL () verwenden können.

67
Bob

Cross-Origin-Attribut für die Bildobjekte setzen, die für mich bearbeitet wurden (ich habe fabricjs verwendet)

    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';

Für diejenigen, die fabricjs verwenden, finden Sie hier den Patch für 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;
};
17
Philip Nuzhnyy

Wenn das Image auf einem Host gehostet wird, für den Access-Control-Allow-Origin oder Access-Control-Allow-Credentials festgelegt ist, können Sie Cross Origin Resource Sharing (CORS) verwenden. Siehe hier (das crossorigin-Attribut) für weitere Details.

Ihre andere Option besteht darin, dass Ihr Server über einen Endpunkt verfügt, der ein Image abruft und bereitstellt. (zB http: // Ihr_Host/Endpunkt? url = URL ) Der Nachteil dieses Ansatzes ist die Latenzzeit und theoretisch unnötiges Abrufen.

Wenn es alternative Lösungen gibt, wäre ich daran interessiert, von ihnen zu hören.

16
James Foster

Anscheinend gibt es eine Möglichkeit, das zu verhindern, wenn Image-Hosting die folgenden HTTP-Header für die Image-Ressourcen und den Browser bereitstellt, die CORS unterstützen:

zugriffskontrollgenehmigung-Ursprung: * 
 Zugriffskontrollgenehmigungsanmeldeinformationen: wahr

Es ist hier angegeben: http://www.w3.org/TR/cors/#use-cases

13
DitherSky

Endlich habe ich die Lösung gefunden. Fügen Sie einfach die crossOrigin als dritten Parameter in fromURL func hinzu

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

Ich konnte es so machen, dass es funktioniert:

Schreiben Sie dies in die erste Zeile Ihres .htaccess auf Ihrem Quellserver

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

Gehen Sie dann beim Erstellen eines <img>-Elements folgendermaßen vor:

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

Ich hatte das gleiche Problem und alle Bilder werden in derselben Domäne gehostet ... Wenn also jemand das gleiche Problem hat, habe ich das Problem gelöst:

Ich hatte zwei Buttons: eine zum Erzeugen der Leinwand und eine andere zum Erzeugen des Bildes aus der Leinwand. Es hat nur für mich funktioniert und es tut mir leid, dass ich nicht weiß warum, als ich den Code auf den ersten Button geschrieben habe. Wenn ich also klicke, generieren Sie gleichzeitig die Leinwand und das Bild ...

Ich habe immer dieses Sicherheitsproblem, wenn die Codes unterschiedliche Funktionen hatten ... = /

2
CarinaPilar

Sie können keine Leerzeichen in Ihre ID einfügen

Update

Meine Vermutung ist, dass sich das Image auf einem anderen Server befindet als auf dem Sie das Skript ausführen. Ich konnte Ihren Fehler bei der Ausführung auf meiner eigenen Seite duplizieren. Der Fehler funktionierte jedoch in dem Moment, in dem ich ein auf derselben Domain gehostetes Image verwendete. Es ist also sicherheitsbezogen - platzieren Sie das Image auf Ihrer Website. Weiß jemand warum das so ist?

1
Mike Robinson

Ich verwende fabric.js und könnte dies durch Verwendung von toDatalessJSON anstelle von toDataURL beheben:

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

Edit: Nevermind. Dies führt dazu, dass nur das Hintergrundbild in JPG exportiert wird, ohne dass die Zeichnung oben angezeigt wird. Es war also nicht ganz nützlich.

0
horstwilhelm

Wenn Sie nur einige Bilder auf einer Leinwand zeichnen, stellen Sie sicher, dass Sie die Bilder aus derselben Domäne laden.

www.example.com unterscheidet sich von example.com  

Stellen Sie daher sicher, dass Ihre Bilder und die URL, die Sie in Ihrer Adressleiste haben, gleich sind.

0
JonathanC