canvas.toDataURL()がセキュリティ例外をスローするのはなぜですか?


90

十分な睡眠が取れなかったのですか?この次のコード

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

これがうまくいかないはずはありません!誰かがこれを説明できますか?



2
その解決策は、Adobe AIRを使用していない人には役に立たないようです。
ObscureRobot 2013

回答:


67

ではスペックは言います:

origin-cleanフラグがfalseに設定されているキャンバス要素のtoDataURL()メソッドが呼び出されるときは常に、このメソッドはSECURITY_ERR例外を発生させる必要があります。

画像が別のサーバーからのものである場合、toDataURL()を使用することはできないと思います


6
攻撃者がプライベートサイトにある写真の名前を推測できる場合、攻撃者はキャンバスにペイントして新しい画像を自分のサイトに送信することにより、そのコピーを入手することができます。私の観点からの主な制限は、別のサイトのコンテンツを描画しないことですが、攻撃者が予期しないサイトに穴を見つけることができるため、セキュリティが複雑すぎます。
AlfonsoML 2010年

3
サブドメインも重要であることに注意してください。私の経験では、Chromeでは少なくとも、SECURITY_ERR:サブドメイン全体にあると認識される呼び出しを行うとDOM例外18が発生します:1. example.com/some/path/index.html in fooのビデオまたは画像.example.com 2. 1と同じページに移動するが、URL example.com/some/path/index.htmlを入力し、www.example.comのビデオまたは画像に対してtoDataUrl()を呼び出そうとした場合
サム・ダットン

3
@AlfonsoML、多分私は間違っているかもしれませんが、「攻撃者がプライベートサイトにある画像の名前を推測できる場合」、おそらくブラウザでカールを使用せずに画像を取得します。私の見解:パブリックURLパブリックコンテンツ。
kilianc 2012年

4
@ pop850データURLを使用してもこの問題に直面しています。データURLに対してこれを回避できる方法はありますか?
Sujay

6
@kiliancこの制限は、攻撃者がブラウザ(認証Cookieを使用)に画像をフェッチさせ、その内容を攻撃者に送信させないようにするために存在します。攻撃者はあなたのcookieを持っていないため、curlを使用して、あなたが取得することを許可されている同じリソースを取得することはできません。「パブリックURL、パブリックコンテンツ」はかなり欠陥のある考え方です。私のFacebookページにはパブリック向けのコンポーネントがありますが、適切な認証トークンでのみアクセスできるものはたくさんあります。
アプシラー2013

18

画像オブジェクトにクロスオリジン属性を設定するとうまくいきました(私は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;
};

おかげで、それは私にとってChromeで動作します。私はfabric.jsを使用していません
Philip007 2013年

私はfabricjsを使用していますが、解決できませんでした。このコードでこれをどのように行いますか?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'、left:0、top:0}); }; bg_img.src = img_url; }}
2017年

Firefoxでも動作します。
vanowm 2017

16

イメージがAccess-Control-Allow-OriginまたはAccess-Control-Allow-Credentialsのいずれかを設定するホストでホストされている場合は、クロスオリジンリソースシェアリング(CORS)を使用できます。詳細については、ここ(crossorigin属性)を参照してください。

もう1つのオプションは、サーバーが画像をフェッチして提供するエンドポイントを持つことです。(例:http:// your_host / endpoint?url = URL)そのアプローチの欠点は、待ち時間と理論的には不要なフェッチであることです。

他に解決策がある場合は、それらについて聞いてみたいと思います。


こんにちは、私はちょうどそれをしました、私はAccess-Control-Allow-Originを持っています:*画像に、crossorigin = 'anonymous'を持っています。 :DOM例外18
skrat

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はaccess-control-allow-origin:*では機能しません。前者が設定されている場合、後者は、developer.mozilla.org
Silver Gonzales

4

最後に私は解決策を見つけました。funcのcrossOrigin3番目のパラメーターとしてasを追加するだけですfromURL

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

2

私は同じ問題を抱えていて、すべての画像が同じドメインでホストされています...したがって、誰かが同じ問題を抱えている場合は、ここで私が解決した方法です:

私には2つのボタンがありました。1つはキャンバスを生成するボタンで、もう1つはキャンバスから画像を生成するボタンです。最初のボタンにすべてのコードを書き込んだとき、それは私のためだけに機能し、なぜかわかりません。クリックすると、キャンバスと画像が同時に生成されます...

コードが異なる関数にある場合、私は常にこのセキュリティ問題を抱えています... = /


2

私はこれを使用してそれを機能させることができました:

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

1

IDにスペースを入れることはできません

更新

私の推測では、画像はスクリプトを実行しているサーバーとは異なるサーバー上にあります。自分のページで実行したときにエラーを再現することができましたが、同じドメインでホストされている画像を使用した瞬間、問題なく動作しました。だからそれはセキュリティ関連です-あなたのサイトに画像を置いてください。これが事実である理由を誰かが知っていますか?


0

キャンバスにいくつかの画像を単に描画する場合は、同じドメインから画像を読み込んでいることを確認してください。

www.example.comexample.comとは異なります

したがって、画像とアドレスバーにあるURLが同じであるか、wwwかどうかを確認してください。


0

私はfabric.jsを使用しており、toDataURLの代わりにtoDatalessJSONを使用してこれを解決できます。

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

編集:気にしない。これにより、背景画像のみがJPGにエクスポートされ、上部に描画されないため、結局完全に有用ではありませんでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.