捕获“访问控制允许来源不允许来源”错误

Posted

技术标签:

【中文标题】捕获“访问控制允许来源不允许来源”错误【英文标题】:Catching 'Origin is not allowed by Access-Control-Allow-Origin' error 【发布时间】:2017-01-10 16:12:57 【问题描述】:
img = new Image();

img.crossOrigin = "anonymous";

try 
    cimg.src = document.getElementById("url").value;

catch(err) 
    alert("Cannot access image.Cross-Domain access blocked");
;

所以,我想检测/捕获跨域访问阻止错误。

经过一番思考,我发现它的 src 加载是异步的,因此 catch 块不起作用。有什么方法可以检测到错误,以便我可以有效地处理它?

【问题讨论】:

您可以加载跨域图像,您只是无法读取它们的像素。因此在 img 加载期间永远不会发生 cors 错误。 那么,本质上是在图像加载后发生 cors 吗?那么在img加载它们之后我如何检测cors? :$ 我需要区分由于错误的 url 而导致的 cors 和 img 加载失败 @DebanjanDhar - 澄清一下,您想检查您加载的图像是否可以被“操纵”,而不仅仅是在<img><object> 标签中显示的资源。对吗? @JaromandaX 是的 【参考方案1】:

正如@TamasHegedus 评论的那样,图像仍然可以加载并出现 CORS 错误,但它不允许操作图像数据。这意味着您可以使用画布尝试操作图像并捕获任何抛出的错误。

这种技术适用于画布支持的图像。如果您想要使用Image#crossOrigin 属性的更简单的替代方案,请参阅@Kaiido 的answer。他的解决方案还检测是否支持该属性,并在必要时使用画布。

// Must work in IE9+.

var img = new Image;

img.onload = function() 

    var canvas = document.createElement('canvas');

    // resize the canvas, else img won't be rendered
    canvas.width = img.width;
    canvas.height = img.height;

    // get the canvas rendering context 2d
    var ctx = canvas.getContext('2d');

    // draw the image first
    ctx.drawImage(img, 0, 0);

    try 
        /* get first pixel */
        ctx.getImageData(0, 0, 1, 1);

        /* no error catched – no cors error */
        alert("Cross-domain access available.");

     catch (e) 
        alert("Cross-domain access blocked.");
    
;

img.src = 'https://i.stack.imgur.com/Kt3vI.png?s=48&g=1';

【讨论】:

您可以将图像完全画在屏幕外,宽度为 0 0 px,但它仍然会污染您的画布。一旦画布被污染,你就无法解除它的污染。本着同样的精神,无需获取全尺寸的 imageData,单个像素将触发 Exception。【参考方案2】:

在支持 crossOrigin 请求的浏览器(应该是首选的)中,如果您将 crossOrigin 设置为 'anonymous',并尝试将元素的 src 指向托管在设置不正确的服务器上的文件,load 事件不会触发,而是error 事件会触发。

重要的是要了解,在跨域请求失败的情况下,服务器将直接回答它不接受请求,因此在您的用户和远程服务器之间只发送标头,而做其他方式周围(首先尝试不使用 crossOrigin 请求,然后尝试使用),您必须先完全下载资源*,然后使用 crossOrigin 属性集再次下载...

同样适用于音频、视频和 xhr 请求。

所以应该先设置跨域请求的crossOrigin,如果失败则说明另一只手没有正确配置。

var img = new Image();
if('crossOrigin' in img)
  // an up to date browser
  // make a single crossOrigin request
  img.crossOrigin = 'anonymous';
  img.onerror = handleCORSFailure;
  
else
  // for browser that don't support the crossOrigin request
  var ctx = document.createElement('canvas').getContext('2d');
  ctx.width = ctx.height = 1; // no need to use too much memory, 1*1 px is enough
  img.addEventListener('load', function()
    ctx.drawImage(this,0,0);
    try
      ctx.getImageData(0,0,1,1);
      
    catch(e)
      handleCORSFailure(e);
      return;
      
    );
  

img.src = 'https://i.stack.imgur.com/Kt3vI.png?s=48&g=1';

function handleCORSFailure(e)
  if(e.target)
    console.log('server not set correctly');
    
  else
    console.log("browser doesn't support crossOrigin requests");
    
 

-* 其实只需要完整下载图片,其他资源都可以测试完再结束。

Ps : 如果是同源请求,crossOrigin 属性应该不会受到伤害,所以这个检查仍然可以进行。

【讨论】:

以上是关于捕获“访问控制允许来源不允许来源”错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 Axios 从 laravel 控制器捕获错误

未捕获的 PDOException:SQLSTATE[42000]:语法错误或访问冲突

带有消息“SQLSTATE [42000]”的未捕获异常“PDOException”:语法错误或访问冲突:

未捕获的错误:引发了跨域错误。 React 无法访问开发中的实际错误对象

致命错误:未捕获的 PDOException:SQLSTATE[42000] 语法错误或访问冲突

致命错误:未捕获的异常“PDOException”,带有消息“SQLSTATE [42000]:语法错误或访问冲突 PHP 和 PDO