Wil*_*ood 6 gwt google-chrome webgl libgdx html5-canvas
我在过去48小时内学到了很多关于跨域策略的知识,但显然还不够.
继这个问题之后.我的HTML5游戏支持Facebook登录.我正在尝试下载人们朋友的个人资料照片.在我的游戏的HTML5版本中,我在Chrome中遇到以下错误.
detailMessage:"com.google.gwt.core.client.JavaScriptException :( SecurityError)↵stack:错误:无法在'WebGLRenderingContext'上执行'texImage2D':可能无法加载受污染的画布.
据我所知,出现此错误是因为我正在尝试从其他域加载图像,但这可以使用Access-Control-Allow-Origin标头解决,详见此问题.
我试图从中下载的URL是
https://graph.facebook.com/1387819034852828/picture?width=150&height=150
查看Chrome中的网络标签,我可以看到它具有所需的access-control-allow-origin标头,并通过302重定向到新URL进行响应.该URL有所不同,我想这取决于负载平衡,但这是一个示例URL.
此URL还具有access-control-allow-origin标头.所以我不明白为什么会失败.
作为Facebook,以及成千上万的应用程序,游戏和网站显示用户个人资料图片的事实,我认为这是可能的.我知道我可以通过我自己的服务器弹跳,但我不知道为什么我应该这样做.
我最终使用以下代码在libgdx中进行跨域映像加载(这非常hacky,我确信可以改进).我还没有设法使用AssetDownloader.我希望最终可以解决这个问题.
public void downloadPixmap(final String url, final DownloadPixmapResponse response) {
final RootPanel root = RootPanel.get("embed-html");
final Image img = new Image(url);
img.getElement().setAttribute("crossOrigin", "anonymous");
img.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
HtmlLauncher.application.getPreloader().images.put(url, ImageElement.as(img.getElement()));
response.downloadComplete(new Pixmap(Gdx.files.internal(url)));
root.remove(img);
}
});
root.add(img);
}
interface DownloadPixmapResponse {
void downloadComplete(Pixmap pixmap);
void downloadFailed(Throwable e);
}
Run Code Online (Sandbox Code Playgroud)
gma*_*man 18
你crossOrigin在申请之前在你的img上设置属性吗?
var img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://graph.facebook.com/1387819034852828/picture?width=150&height=150";
Run Code Online (Sandbox Code Playgroud)
当问到这个问题时,这对我有用.不幸的是,上面的URL不再指向任何内容,因此我在下面的示例中对其进行了更改
var img = new Image();
img.crossOrigin = "anonymous"; // COMMENT OUT TO SEE IT FAIL
img.onload = uploadTex;
img.src = "https://i.imgur.com/ZKMnXce.png";
function uploadTex() {
var gl = document.createElement("canvas").getContext("webgl");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
try {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
log("DONE: ", gl.getError());
} catch (e) {
log("FAILED to use image because of security:", e);
}
}
function log() {
var div = document.createElement("div");
div.innerHTML = Array.prototype.join.call(arguments, " ");
document.body.appendChild(div);
}Run Code Online (Sandbox Code Playgroud)
<body></body>Run Code Online (Sandbox Code Playgroud)
如何检查您是否收到了标题
打开您的devtools,选择网络选项卡,重新加载页面,选择有问题的图像,查看REQUEST标头和RESPONSE标头.
该请求应显示您的浏览器发送了Origin:标题
回复应该表明你收到了
Access-Control-Allow-Methods: GET, OPTIONS, ...
Access-Control-Allow-Origin: *
Run Code Online (Sandbox Code Playgroud)
请注意,响应和请求都必须显示上面的条目.如果请求丢失,Origin:那么您没有设置img.crossOrigin,即使响应表明它没问题,浏览器也不会让您使用该图像.
如果您的请求具有Origin:标头且响应没有其他标头,则该服务器未授予使用该图像显示它的权限.换句话说,它将在图像标签中工作,你可以将它绘制到画布上,但你不能在WebGL中使用它,你绘制的任何2d画布都会被污染,toDataURL并且getImageData会停止工作