Webgl 跨域图像不起作用

Posted

技术标签:

【中文标题】Webgl 跨域图像不起作用【英文标题】:Webgl Cross Origin Images don't work 【发布时间】:2018-03-07 10:27:03 【问题描述】:

我遇到了一些跨域图片的问题,希望你能帮忙。

这里的行为。 我有 2 个域,例如: - domain1.com - domain2.com

在 domain1 上我放了很多 html5 游戏。此域只是游戏的存储库。

Domain2 是真正的网站(wordpress 网站),用户可以在其中玩 domain1 上托管的游戏。 为此,我为每场比赛都提出了 curl 请求。

在 domain1 nginx 配置文件中,我将这些代码行用于启用跨域资源共享:

位置~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|json|js|jpg|jpeg|gif|png|ico|zip|tgz|gz| rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf|mp3|xml|woff2)$ add_header "Access-Control-Allow-Origin" "*"; access_log 关闭; log_not_found 关闭; 最大过期;

这解决了许多游戏的一些问题,但有些游戏仍然无法运行,我收到这个 js 错误:

未捕获的 DOMException:无法在“WebGLRenderingContext”上执行“texImage2D”:可能无法加载 http://domain1.com/html5-games/action/candy-match/images/loadingbarbackground-sheet0.png 处的跨域图像。 在 GLWrap_.loadTexture (http://domain1.com/html5-games/action/candy-match/c2runtime.js:2618:16) 在 pluginProto.Type.typeProto.loadTextures (http://domain1.com/html5-games/action/candy-match/c2runtime.js:18070:46) 在 pluginProto.Instance.instanceProto.onCreate (http://domain1.com/html5-games/action/candy-match/c2runtime.js:18146:13) 在 Runtime.createInstanceFromInit (http://domain1.com/html5-games/action/candy-match/c2runtime.js:4806:8) 在 Layer.createInitialInstances (http://domain1.com/html5-games/action/candy-match/c2runtime.js:7541:25) 在 Layout.startRunning (http://domain1.com/html5-games/action/candy-match/c2runtime.js:6715:10) 在 Runtime.go_loading_finished (http://domain1.com/html5-games/action/candy-match/c2runtime.js:4067:36) 在 Runtime.go (http://domain1.com/html5-games/action/candy-match/c2runtime.js:3966:9) 在 http://domain1.com/html5-games/action/candy-match/c2runtime.js:4025:60

我在网上做了一些研究,发现了这样的文章 https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html Drawing images to canvas with img.crossOrigin = "Anonymous" doesn't work

但它们不是很有帮助。

我不想修改原始游戏文件。如果存在,我正在寻找服务器端解决方案。如果没有,您有解决我的问题的想法吗?

我的配置有错误吗?我错过了什么吗?

感谢您的帮助。

瓦莱里奥

【问题讨论】:

您是否通过浏览器开发工具检查过您的 domain1 服务器是否确实返回了正确的标头? 嗨@CBroe 显然标头似乎没问题。HTTP/1.1 200 OK 服务器:nginx/1.6.2 日期:星期二,2017 年 9 月 26 日 09:33:11 GMT 内容类型:文本/html 内容-长度:4431 最后修改时间:2017 年 9 月 26 日星期二 08:00:45 GMT 连接:保持活动 ETag:“59ca092d-114f”接受范围:字节 我的意思是图片... 呃,对不起@CBroe,这是我为图片获取的标题imgur.com/a/huxPq 尝试将访问控制标头设置为实际域而不是通配符,也可以尝试其他浏览器以获取更详细的错误消息。 【参考方案1】:

游戏必须请求跨源图像。仅仅返回正确的标题是不够的。如果游戏本身没有通过设置crossOrigin 属性请求跨源图像,那么即使图像具有正确的标头,浏览器也不会允许使用这些图像。

这是一个例子

const gl = document.createElement("canvas").getContext("webgl");
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);

loadImage('https://i.imgur.com/ZKMnXce.png', false);
loadImage('https://i.imgur.com/u6VI8xz.jpg', true);

function loadImage(url, crossOrigin) 
  const img = new Image();
  img.onload = () =>  upload(img); ;
  if (crossOrigin) 
    img.crossOrigin = '';
  
  img.src = url;


function upload(img) 
  // trap for cors error
  try 
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    log(img.src, "uploaded image");
   catch (e) 
    log(img.src, e);
  


function log(...args) 
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(' ');
  document.body.appendChild(elem);
pre  margin: 0; 

在这里您甚至可以看到第一张图片返回了不允许使用的 CORS 标头,因为未设置 crossOrigin

第二张图片有相同的标题,但它可以工作,因为我们设置了crossOrigin 属性

请注意,您可能可以在游戏脚本之前包含这样的脚本,以对 CORS 支持进行某种破解。

(function() 

function isSameOrigin(url) 
  return (new URL(url, window.location.href)).origin === window.location.origin;


function needsCORS(url) 
  // not sure all the URLs that should be checked for
  return !isSameOrigin(url) && !url.startsWith("blob:") && !url.startsWith("data:");


const srcSetFn = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src').set; 

Object.defineProperty(HTMLImageElement.prototype, 'src', 
  enumerable: true,
  set: function(url) 
     if (needsCORS(url)) 
       // Set if not already set
       if (this.crossOrigin !== undefined) 
         this.crossOrigin = '';
       
      else 
       this.crossOrigin = undefined;
     
     // Set the original attribute
     srcSetFn.call(this, url);
  ,
);

());

【讨论】:

【参考方案2】:

http://webgl-hooman.blogspot.ca/2018/01/cross-origin-image-cannot-be-loaded-in.html

CORS = 跨源资源共享。这是网页向图像服务器请求使用图像的一种方式。跨源是谷歌浏览器内置的安全保护,不允许用户访问本地文件(在这种情况下是您的图像/纹理) .即使在 Safari 中,您也会收到“操作不安全”的错误。你有几个选择。最简单的方法是让您的 webgl 应用程序从 IIS 或 Apache 等 Web 服务器运行。如果您使用的是 Windows,另一种选择是使用 Internet Explorer 或 Microsoft Edge 浏览器打开您的 webgl 应用程序。如果您使用“FireFox”浏览器从 Mac 运行 webgl 应用程序,请将 crossorigin="anonymous" 添加到 HTML 中的图像标签中,您的纹理正在被加载。但是,如果您使用“Windows”操作系统或任何其他浏览器,即使在 Mac 中,这将不起作用!它仅适用于 MAC+Firefox。所以要么把你的图片标签改成这个,要么简单地添加这个 var image = document.getElementById("texImage"); image.crossOrigin = "";更多信息,请阅读:https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html

【讨论】:

以上是关于Webgl 跨域图像不起作用的主要内容,如果未能解决你的问题,请参考以下文章

CORS:PHP绕过不起作用

Autodesk AR/VR Toolkit 请求在 Unity3d WEBGL 中不起作用?

跨域 AJAX 请求不起作用

Chrome 跨域补丁请求不起作用

跨域中的引导字形图标不起作用

具有跨域 Ajax 的 WCF Web 服务不起作用