-1

I am doing a verification code to automatically fill in the plugin, but I have encountered an error.

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

Error Image: https://img-ask.csdn.net/upload/201902/03/1549128446_976961.png

The corresponding code is:

Code Image https://img-ask.csdn.net/upload/201902/03/1549128473_324557.png

function getBase64Image(im)
{
    im.crossOrigin="";
    var canvas = document.createElement("canvas");
    canvas.width = im.width;
    canvas.height = im.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(im, 0, 0);
    var dataURL = canvas.toDataURL("image/png");
    return dataURL.replace("data:image/png;base64,", "");
}

I found a lot of solutions in Google, mostly telling me that this is a cross-domain error. solutions

I can add code to be

img.crossOrigin="Anonymous";

Resolve cross-domain issues, but still give an error after trying Next, I found a solution to this type of problem on stackoverflow.

Got it

img.crossOrigin="";

Still added after the addition

This solution is feasible on other pages, that is, this page cannot be killed or killed.

Test

Test URL:Click here to jump to the Alipay login page

1.Enter a function in the Console

Such as:

function getBase64Image(im)
{
  im.crossOrigin="";
    var canvas = document.createElement("canvas");
  canvas.width = im.width;
    canvas.height = im.height;
    var ctx = canvas.getContext("2d");
  ctx.drawImage(im, 0, 0);
  var dataURL = canvas.toDataURL("image/png");
    return dataURL.replace("data:image/png;base64,", "");
}

2.Next

getBase64Image(document.getElementById("J-checkcode-img"))

I don't know much about JavaScript development.

I haven't found a suitable solution on the Internet for a long time.

I don't know how to solve it. I hope you can help, thank you!

jakobinn
  • 1,832
  • 1
  • 20
  • 20
wjh
  • 1
  • This guy suggests proxying the image through your server so it appears to be from the same domain thereby avoiding any CORS related issues: https://ourcodeworld.com/articles/read/182/the-canvas-has-been-tainted-by-cross-origin-data-and-tainted-canvases-may-not-be-exported – Synthetx Feb 04 '19 at 02:26

1 Answers1

1

In your research it seems you read on the crossOrigin attribute, which indeed is required for being able to access cross-origin resources' data.

However, it seems you didn't clearly got how it works.

This attribute is a flag for the browser to know if they must request the resource fetched by the Element with CORS headers, so that the server can send them the response with the proper Allow-Origin headers (or with a denial).

But this attribute doesn't call anything by itself, it is juts a flag and is only visited when the Element's resource is being fetched.
This means that for it to have any effect, you must set it before setting the Element's src.

So when in your code you do im.crossOrigin = ""; since you don't set the src again after this setting, the resource fetched doesn't have the proper Allow-Origin headers, and the resource is marked as violating the Same-Origin Policies and will thus taint your canvas.

Now, note that some browsers do require that the server sends at least an Vary: Origin header, or even Allow-Origin: *, even for requests that are willing to be Cross-Origin. see more.

So the best is to set the crossOrigin attribute from the first request, you don't show where it is in your code, but here are both possible cases:

onload = e => {
  const img2 = new Image();
  img2.crossOrigin = ""; // set it before setting the src
  img2.onload = draw; // wait it's loaded
  img2.src = "https://commons.wikimedia.org/static/images/project-logos/commonswiki.png";
};

function draw(evt) {
  const img1 = document.getElementById('img1');
  const img2 = this;

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.height = 200;
  ctx.drawImage(img2,50,0,200,200);
  ctx.drawImage(img1,0,0,300,200);
  // export to an <img> in body
  canvas.toBlob( blob =>
    document.body.appendChild(new Image())
      .src = URL.createObjectURL(blob)
  );
  
}
#img1{
  display: none;
}
<!-- set the attribute in the markup directly -->
<img id="img1" crossOrigin="anonymous" src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png">

And of course, this assumes that your server is properly configured to accept anonymous requests.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Thanks,I am doing a verification code to automatically fill in the plugin,so maybe I can't configure the server correctly. But what you said is still very inspiring to me, maybe I should think about whether this plugin should continue to do it. – wjh Feb 04 '19 at 15:20