【问题标题】:"Access is Denied" on contentDocument in IE9 on same domain [duplicate]同一域上 IE9 中 contentDocument 的“访问被拒绝”[重复]
【发布时间】:2014-09-12 10:19:42
【问题描述】:

短版/通用版:

我正在开发一个应用程序(不幸的是,由于其他原因),将每个页面顶部的 document.domain 设置为“真实”域的子字符串:对于像 sub.app.localdocument.domain = "app.local" 这样的子域。我还在动态创建一个 iframe 并将其添加到页面中。 iframe 加载与父页面位于同一服务器上的文件。稍后,一些 Javascript 需要访问 iframe 的 contentDocument 属性。

这在现代浏览器中很好,但在 IE9 中由于this bug 而导致问题。 (请参阅top answer 以很好地解释为什么会这样。)AFAIK,每个比 IE9 更新的浏览器都会自动继承 document.domain 以编程方式创建的 iframe,所以这是特定于 IE9 的。由于我的场景的一些独特要求(tldr:iframe src 需要更改),上面帖子中的答案对我不起作用。

更长的/特定于应用程序的版本:

我在 IIS 上运行的应用程序中使用 FineUploader,将文件上传到 S3。在现代浏览器中一切正常,但 IE9 支持给我带来了麻烦,即使按照文档 (Supporting IE9 and older) 配置 iframeSupport.localBlankPagePath 选项也是如此。我有点难过!

  • 我在 FineUploader 4.0.3 和 5.0.3 上都试过了。
  • 在 IE11 中一切正常。如果我在 F12 控制台中将文档模式切换到 9,它就会中断。
  • 我没有打开 CORS 支持,因为我没有从其他域加载任何内容。
  • 我在与我的页面相同的域中有一个虚拟/空白文件。
  • 我可以看到(在网络面板中)来自 AWS 的 HTTP 303 响应,其中包括 Location 键和指向我的空白文档的值。如果我将整个 URL 粘贴到地址栏中,页面加载正常,并且按预期显示为空白。
  • 我尝试按照here 的建议将X-Frame-Options SAMEORIGIN 添加到服务器的响应标头中,但没有帮助。

我在控制台中得到的错误是:

[Fine Uploader 5.0.3] Error when attempting to access iframe during handling of upload response (Access is denied.
)
[Fine Uploader 5.0.3] Amazon likely rejected the upload request



更新

我已经确定它不能开箱即用的原因是应用程序在页面加载时设置了document.domain,它不同于location.host 的(一个子集)。 FineUploader 的空白页 303 重定向机制工作正常,但 iframe 的 document.domain 与父级不同(由于 IE9 未继承该属性),因此拒绝访问。

实际的 S3 上传工作。这只是验证上传失败的最后一步。

这是我的客户端代码:

FineUploader.js

var fu = namespace('App.FineUploader');
fu.DocId;
fu.ClientDeployId;
fu.viewModel;
fu.defaultAttachmentEndpoint = "https://s3.amazonaws.com/App.UploadBucket";
fu.FineUploaderController = "FineUploaderDocAttachment";

fu.delete = function (documentAttatchmentID, attachmentID) {
    var data = documentAttatchmentID;
    $.ajax({
        type: "POST",
        url: App.BaseUrl + "/api/" + fu.FineUploaderController + "/delete",
        data: JSON.stringify(data),
        success: function () {
            $('#fineUploader' + attachmentID).fineUploader('reset');
            $('#fineUploader' + attachmentID).show();
            $('#aDownloadfineUploader' + attachmentID).html('');
            $('#aDownloadfineUploader' + attachmentID).hide();
            $('#aDeletefineUploader' + attachmentID).hide();
        },
        dataType: 'json',
        contentType: 'application/json'
    })
}

fu.lockAll = function () {
    $('.fineUploader').hide();
    $('a[id^="aDeletefineUploader"]').hide();
}

fu.init = function (sID) {
    $('#' + sID).fineUploaderS3({
        request: {
            endpoint: fu.defaultAttachmentEndpoint,
            accessKey: "[key]",
            params: {
                documentid: $('#' + sID).attr('documentid'),
                attachmentid: $('#' + sID).attr('attachmentid')
            }
        },
        signature: {
            endpoint: App.BaseUrl + "/api/" + fu.FineUploaderController + "/signtureHandler"
        },
        uploadSuccess: {
            endpoint: App.BaseUrl + "/api/" + fu.FineUploaderController + "/success"
        },
        iframeSupport: {
            localBlankPagePath: App.BaseUrl + "/Scripts/FineUploader/4.0.3/html/blank.html"
        },
        objectProperties: {
            key: function (fileId) {
                var keyRetrieval = new qq.Promise(),
                    filename = $('#' + sID).fineUploader("getName", fileId);
                var documentid = $('#' + sID).attr('documentid');
                var attachmentid = $('#' + sID).attr('attachmentid');
                var data = { name: filename, documentId: documentid, attachmentId: attachmentid }
                $.ajax({
                    type: "POST",
                    url: App.BaseUrl + "/api/" + fu.FineUploaderController + "/preUpload",
                    data: JSON.stringify(data),
                    success: null,
                    dataType: 'json',
                    contentType: 'application/json'
                }).done(function (data) {
                    keyRetrieval.success(data.key);
                }).fail(function () {
                    keyRetrieval.failure();
                });
                return keyRetrieval;
            }
        },
        validation: {
            itemLimit: 1
        },
        chunking: {
            enabled: true
        }
    }).on('error', function (event, id, name, errorReason, xhrOrXdr) {
        alert(qq.format("Error on file number {} - {}.  Reason: {}", id, name, errorReason));
    }).on('complete', function (event, id, name, response) {
        if (fu.FineUploaderController === "FineUploaderDocLibraryAttachment") {
            $('#' + sID).fineUploader('reset');
            App.Contracts.Create.ReloadImageLibraryList(true);
            App.Contracts.Create.HideLoader();
        } else {
            $('#aDownload' + sID).attr('href', response.url);
            $('#aDownload' + sID).html(response.name);
            $('#aDownload' + sID).show();
            $('#aDelete' + sID).show();
            $('#aDelete' + sID).attr('onclick', 'App.FineUploader.delete(' + response.daId + ',' + sID.replace('fineUploader', '') + ');');
            $('#' + sID).hide();
        }
    }).on('submitted', function () {
        if (fu.FineUploaderController === "FineUploaderDocLibraryAttachment") {
            App.Contracts.Create.ShowLoader();
        }
    });
}

【问题讨论】:

  • 您是否尝试过授予 IIS 管理员权限?这是一个常见的错误来源。
  • 我很确定这不是问题所在,因为父应用程序目前正在我们的生产服务器上运行,没有任何问题。 (除非这是此处相关文件之一的特定权限问题。)
  • 你用的是原生 IE9,还是 IE11 中的 quirks-mode 开关?存在差异,并且已知怪癖模式会导致问题。
  • 我相信您需要确保返回的 iframe 的 content-type 也是 text/html
  • 您需要显示您的客户端代码才能获得任何有用的帮助。您需要告诉我们该文件是否真正进入 S3(成功)。

标签: javascript internet-explorer internet-explorer-9 fine-uploader


【解决方案1】:

(如果有人在 FineUploader 的上下文之外偶然发现这个答案,this idea 是我的解决方案的基础。)

为了实现这一点,我将 FineUploader 的 blank.html 设为非空白:

<head>
<script type="text/javascript">
    // Provide a mechanism to override document.domain
    // inside the iframe via this url syntax: blank.html?[args]#domain.com
    if (location.hash.substring(1).length > 0)
        document.domain = location.hash.substring(1);
</script>
</head><body></body>

这使我可以在生成 iframe 时从父页面提供正确的 document.domain 值。对 FineUploader 配置对象稍作修改:

$.fineUploaderS3({
[snip]
    iframeSupport: {
        localBlankPagePath: App.BaseUrl + "/Scripts/FineUploader/4.0.3/html/blank.html#" + document.domain
    },
[/snip]
}

这似乎不会干扰 AWS 预先设置的参数。我们仍在此应用程序中使用 FineUploader 4.0.3,但这应该也适用于最新版本。

tl,dr; 有效!在 IE11 文档模式和原生 IE9 中测试。

【讨论】:

  • 请注意,iframeSupport 选项不是必需的,因此在 IE10+ 中被忽略。其实这个只用在IE7-9中。
  • @RayNicholus 有道理,我也这么认为。感谢您的澄清。
【解决方案2】:

该错误表明 iframe 提供的页面确实与托管上传程序的页面不在同一个域。要么,要么你有一些插件/扩展造成麻烦。根据错误,Fine Uploader 根本无法访问 iframe 中的任何内容,当 iframe 的域与承载上传器的框架/页面的域不匹配时,就会发生这种情况。

【讨论】:

  • 是的,页面前面的一些 Javascript 确实将域设置为其他内容(基本域,没有子域部分)。我在下面发布了我的解决方案。我不确定它是否“最好”,但它确实有效。
猜你喜欢
  • 2012-06-14
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多