कैनवस .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 का उपयोग न करने वाले लोगों के लिए उपयोगी नहीं लगता है।
ऑबस्क्यूररॉट

जवाबों:


67

में चश्मा यह कहते हैं:

जब भी एक तत्त्व तत्व का toDataURL () विधि जिसके मूल-स्वच्छ ध्वज को गलत पर सेट किया जाता है, उसे कहा जाता है, तो विधि को SECURITY_ERR अपवाद को उठाना चाहिए।

यदि छवि किसी अन्य सर्वर से आ रही है तो मुझे नहीं लगता कि आप toDataURL () का उपयोग कर सकते हैं


6
यदि कोई हमलावर किसी निजी साइट पर आपके पास मौजूद किसी चित्र के नाम का अनुमान लगाने में सक्षम है, तो वह कैनवास पर पेंटिंग करके और अपनी साइट पर नई छवि भेजकर इसकी एक प्रति प्राप्त कर सकेगा। मेरे दृष्टिकोण से मुख्य प्रतिबंध किसी अन्य साइट की सामग्री को आकर्षित करने से बचने के लिए है, लेकिन सुरक्षा बहुत जटिल है क्योंकि हमलावर किसी भी अप्रत्याशित साइट में एक छेद पा सकता है।
अल्फांसोएमएल

3
ध्यान दें कि उपडोमेन भी मायने रखता है। मेरे अनुभव में, Chrome में कम से कम, SECURITY_ERR: DOM एक्सेप्शन 18 तब उठाया जाता है जब कॉल को उप-डोमेन में माना जाता है: 1. उदाहरण में। वीडियो में foo में एक वीडियो या छवि के लिए //ath/index.html .example.com 2. जब एक ही पृष्ठ पर 1 के रूप में जा रहा हो, लेकिन URL example.com/some/path/index.html दर्ज करके और फिर www.example.com में एक वीडियो या छवि के लिए toDataUrl () को कॉल करने का प्रयास कर रहा हो।
सैम डटन

3
@AlfonsoML, शायद मैं गलत हूं, लेकिन "अगर कोई हमलावर एक निजी साइट में आपके पास मौजूद किसी चित्र के नाम का अनुमान लगाने में सक्षम है" तो शायद वह एक ब्राउज़र के साथ कर्ल नॉन के साथ छवि को पकड़ लेगा। मेरा नज़रिया: सार्वजनिक URL सार्वजनिक सामग्री।
किलियनक

4
@ pop850 जब मैं डेटा URL का उपयोग करता हूं तब भी मैं इस समस्या का सामना कर रहा हूं। क्या कोई तरीका है कि मैं डेटा URL के लिए इसे हल कर सकता हूं?
सुजय

6
@kilianc यह प्रतिबंध एक हमलावर को आपके ब्राउज़र को उत्पन्न करने से रोकने के लिए मौजूद है (प्रमाणीकरण कुकीज़ के साथ) एक छवि लाने के लिए और एक हमलावर को इसकी सामग्री भेजने के लिए; हमलावर के पास आपकी कुकीज़ नहीं हैं, इसलिए वह उसी संसाधनों को प्राप्त करने के लिए कर्ल का उपयोग नहीं कर सकता है जिसे आप प्राप्त करने के लिए अधिकृत हैं। "सार्वजनिक URL, सार्वजनिक सामग्री" सोच का एक त्रुटिपूर्ण तरीका है: मेरे फेसबुक पेज पर सार्वजनिक रूप से सामना करने वाले घटक हैं, लेकिन बहुत कुछ है जो केवल सही प्रमाणीकरण टोकन के साथ उपलब्ध है।
अप्सिलर्स

18

मेरे लिए काम की छवि वस्तुओं पर क्रॉस मूल विशेषता सेट करना (मैं फैब्रिक का उपयोग कर रहा था)

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

धन्यवाद, यह क्रोम में मेरे लिए काम करता है। मैं फैब्रिक का उपयोग नहीं कर रहा हूं। हालांकि
फिलिप ४००

मैं फैब्रिक का उपयोग करता हूं, लेकिन इसे हल नहीं कर सका। आप इस कोड के साथ ऐसा कैसे करेंगे? function wtd_load_bg_image (img_url) {if (img_url) {var bg_img = new Image (); bg_img.onload = function () {कैनवसओबीजे.सेटबेकग्राउंडइमेज (bg_img.src, कैनवसओबीजे.रेंडरएएल.बिंद (कैनवसऑब्ज), {ओरिजिनएक्स: 'लेफ्ट', ओरिजिन: 'टॉप', लेफ्ट: 0, टॉप: 0}; }; bg_img.src = img_url; }}
HOY

फ़ायरफ़ॉक्स में भी काम करता है।
2

16

यदि छवि को किसी होस्ट पर होस्ट किया गया है जो एक्सेस-कंट्रोल-अलाउंस-ओरिजिन या एक्सेस-कंट्रोल-एलाउंस-क्रेडेंशियल्स सेट करता है, तो आप क्रॉस ओरिजिन रिसोर्स शेयरिंग (कोर) का उपयोग कर सकते हैं। अधिक विवरण के लिए यहां देखें (क्रॉसोरिजिन विशेषता)।

आपका अन्य विकल्प आपके सर्वर के लिए एक समापन बिंदु है जो एक छवि प्राप्त करता है और कार्य करता है। (उदा। http: // your_host / endpoint? url = URL ) उस दृष्टिकोण का नकारात्मक पक्ष विलंबता और सैद्धांतिक रूप से अनावश्यक खुजली है।

यदि अधिक वैकल्पिक समाधान हैं, तो मुझे उनके बारे में सुनने में दिलचस्पी होगी।


नमस्ते, मैंने बस यही किया, मेरे पास Access-Control-Allow-Origin है: * छवियों पर, मेरे पास crossorigin = 'अनाम' है, फिर मैं कैनवास पर छवि को चित्रित करता हूं, फिर मैं toDataUrl को कॉल करता हूं और मुझे अभी भी SECURL_ERR मिल रहा है। : डोम एक्सेप्शन 18
स्कॉर्ट

13

लगता है कि इसे रोकने का एक तरीका है कि यदि छवि होस्टिंग छवि संसाधनों और ब्राउज़र के लिए निम्नलिखित HTTP हेडर प्रदान करने में सक्षम है, तो CORS का समर्थन करता है:

अभिगम-नियंत्रण-अनुमति-उत्पत्ति: *
पहुँच-नियंत्रण-अनुमति-क्रेडेंशियल्स: सच

यह यहाँ कहा गया है: http://www.w3.org/TR/cors/#use-cases


1
access-control-allow-क्रेडेंशियल: true, access-control-allow-origin के साथ काम नहीं करेगा: *। जब पूर्व सेट किया जाता है, तो उत्तरार्द्ध का मूल मान होना चाहिए, न कि developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
सिल्वर गोंजालेस

4

अंत में मुझे समाधान मिल गया। बस func crossOriginमें तीसरे परम के रूप में जोड़ने की जरूरत हैfromURL

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

2

मुझे एक ही समस्या थी और सभी छवियों को एक ही डोमेन में होस्ट किया गया है ... इसलिए, अगर किसी को एक ही समस्या हो रही है, तो यहां बताया गया है:

मेरे पास दो बटन थे: एक कैनवास उत्पन्न करने के लिए और दूसरा कैनवास से छवि उत्पन्न करने के लिए। यह केवल मेरे लिए काम करता है, और खेद है कि मुझे नहीं पता कि क्यों, जब मैंने पहले बटन पर सभी कोड लिखे थे। इसलिए जब मैं क्लिक करता हूं तो यह एक ही समय में कैनवास और छवि उत्पन्न करता है ...

जब कोड अलग-अलग फ़ंक्शंस पर होते हैं तो मुझे हमेशा यह सुरक्षा समस्या होती है ... = /


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

आप अपनी आईडी में स्पेस नहीं डाल सकते

अपडेट करें

मेरा अनुमान है कि छवि एक अलग सर्वर पर है जहाँ आप स्क्रिप्ट निष्पादित कर रहे हैं। जब मैं इसे अपने पेज पर चला रहा था, तो मैं आपकी त्रुटि का डुप्लिकेट करने में सक्षम था, लेकिन इसने ठीक उसी क्षण काम किया जब मैंने उसी डोमेन पर होस्ट की गई छवि का उपयोग किया। तो यह सुरक्षा से संबंधित है - छवि को अपनी साइट पर रखें। किसी को पता है कि यह मामला क्यों है?


0

यदि आप किसी कैनवास पर कुछ चित्र बना रहे हैं, तो सुनिश्चित करें कि आप उसी डोमेन से चित्र लोड कर रहे हैं।

www.example.com example.com के लिए अलग है

इसलिए सुनिश्चित करें कि आपके चित्र और आपके पते के बार में मौजूद url एक ही हैं, www या नहीं।


0

मैं fabric.js का उपयोग कर रहा हूं और इसे toDatalessJSON के बजाय DDataURL का उपयोग करके हल कर सकता हूं:

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

संपादित करें: कोई बात नहीं। इसका परिणाम केवल पृष्ठभूमि की छवि में जेपीजी को निर्यात किया जा रहा है, शीर्ष पर आरेखण के बिना तो यह पूरी तरह से उपयोगी नहीं था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.