gpt4 book ai didi

javascript - 如何在跨源请求后访问 iframe.contentDocument 以获得响应?

转载 作者:行者123 更新时间:2023-11-29 10:41:15 26 4
gpt4 key购买 nike

我成功地从 localhost:8888 发送了一个文件至 localhost:8080 (生产中的不同域),但传输完成后我无法读取 HTTP 响应。

Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://localhost:8888" from accessing a frame with origin "http://localhost:8080". The frame requesting access set "document.domain" to "localhost", but the frame being accessed did not. Both must set "document.domain" to the same value to allow access.

要发送文件,为了兼容性支持,我试图让它为 <form> 工作基于文件上传;不是XHR基于。这是基本的 HTML 结构:

<form target="file-iframe" enctype="multipart/form-data" method="POST" action="invalid">
<input type="file" id="file-input" class="file-input" title="select files">
</form>
<iframe src="javascript:false;" id="file-iframe" name="file-iframe"></iframe>

要插入 <iframe>元素添加到 DOM 中,我执行以下操作:

document.domain = document.domain;
var domainHack = 'javascript:document.write("<script type=text/javascript>document.domain=document.domain;</script>")';

var html = '<iframe id="file-iframe" name="file-iframe"></iframe>';
var parent = document.getElementById('wrapper');
var iframe = UTILS.createDomElement(html, parent);
iframe.src = domainHack;

UTILS.attachEvent(iframe, 'load', function(e) {

// this throws the above SecurityError
var doc = iframe.contentDocument || iframe.contentWindow.document;

// do other stuff...
});

在提交表单之前,我设置了 action <form> 上的属性成为目标跨域 URL:

action="http://localhost:8080/"

提交 <form> 后, <iframe>load事件被触发,我尝试访问 <iframe>的内容来读取 HTTP 响应。但是,这样做会引发上述错误,因为这是一个跨源请求,而且我无权访问 <iframe>。的内容。

我以为 document.domain hack 会起作用,但错误消息告诉我 iframe没有将域设置为 localhost ,即使我设置了 iframesrc属性为 domainHack变量,似乎在执行。

关于我可能做错了什么有什么想法吗?如何设置 document.domain成为localhost对于 <iframe>及其父级(即当前页面)。


我已经通读了几个 StackOverflow 问题、一些 MDN 文章和 Google 上的其他随机结果,但我无法让它发挥作用。我已经看过的一些东西:

最佳答案

在仔细研究并尝试解决这个问题之后,我终于找到了一个似乎对我有用的解决方案。但是,这并不是我的问题的确切答案。

总而言之,我正在努力支持 <form>基于文件上传。对于不支持通过 XHR 上传文件的浏览器,我们不得不求助于传统的<form>提交,使用隐藏的 <iframe>以避免页面刷新。表单将重新加载操作重定向到隐藏的 <iframe> ,然后将 HTTP 响应写入 <iframe> 的正文文件传输后。

由于 same-origin policy ,因此我问这个问题的原因是,我无权访问 <iframe>的内容。 <iframe> 的同源策略s 限制从一个源加载的文档或脚本如何与另一个源的资源交互。由于我们无法访问 <iframe>的文档,这是写入文件上传 HTTP 响应的位置,服务器将返回一个重定向响应,服务器将向其附加上传响应 JSON。当 <iframe>加载后,JS会解析出response JSON,写入到<iframe>中的 body 。最后,由于重定向是同源的,我们可以访问 <iframe>的内容:)

非常感谢 jQuery File Uploader ;他们做了所有艰苦的工作;)

https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads

设置...

JS

function setupForm() {

// form is declared outside of this scope
form = document.createElement('form');
form.setAttribute('id', 'upload-form');
form.setAttribute('target', 'target-iframe');
form.setAttribute('enctype', 'multipart/form-data');
form.setAttribute('method', 'POST');

// set the 'action' attribute before submitting the form
form.setAttribute('action', 'invalid');
};

function setupIframe() {

// iframe is declared outside of this scope
iframe = document.createElement('iframe');

/*
* iframe needs to have the 'name' attribute set so that some versions of
* IE and Firefox 3.6 don't open a new window/tab
*/
iframe.id = 'target-iframe';
iframe.name = 'target-iframe';

/*
* "javascript:false" as initial iframe src to prevent warning popups on
* HTTPS in IE6
*/
iframe.src = 'javascript:false;';
iframe.style.display = 'none';

$(iframe).bind('load', function() {
$(iframe)
.unbind('load')
.bind('load', function() {
try {

/*
* the HTTP response will have been written to the body of the iframe.
* we're assuming the server appended the response JSON to the URL,
* and did the redirect correctly
*/
var content = $(iframe).contents().find("body").html();
response = $.parseJSON(content);

if (!response) {
// handle error
return;
}

uploadFile(...); // upload the next file
}
catch (e) {
// handle error
}
});
});

/*
* insert the iframe as a sibling to the form. I don't think it really
* matters where the iframe is on the page
*/
$(form).after(iframe);
};

HTML - 重定向页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
// grabs the JSON from the end of the URL
document.body.innerHTML = decodeURIComponent(window.location.search.slice(1));
</script>
</body>
</html>

唯一剩下要做的就是设置 action <form> 上的属性到我们将上传发送到的跨域 URL:

form.setAttribute('action', 'http://sub.example.com:8080/upload?id=ab123');
form.submit();

同时,在服务器上...

// send redirect to the iframe redirect page, where the above HTML lives
// generates URL: http://example.com/hack?%7B%22error%22%3Afalse%2C%22status%22%3A%22success%22%7D
response.sendRedirect("http://example.com/hack?{\"error\":false,\"status\":\"success\"}");

我知道这是绕过 <iframe> 的同源策略的大规模黑客攻击。 s,但它似乎可以工作,而且我认为它在跨浏览器兼容性方面相当不错。我尚未在所有浏览器中对其进行测试,但我会着手进行测试,并发布更新。

关于javascript - 如何在跨源请求后访问 iframe.contentDocument 以获得响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28668044/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com