代码之家  ›  专栏  ›  技术社区  ›  Nate Barbettini

同一域上IE9中contentDocument的“访问被拒绝”[重复]

  •  6
  • Nate Barbettini  · 技术社区  · 10 年前

    短/通用版本:

    我正在开发一个应用程序 document.domain 在每个页面的顶部添加到“true”域的子字符串:用于子域,如 sub.app.local , document.domain = "app.local" 。我还在动态创建iframe并将其添加到页面中。iframe加载驻留在与父页相同的服务器上的文件。稍后,一些Javascript需要访问 contentDocument iframe的属性。

    这在现代浏览器中很好,但由于 this bug 。(参见 top answer 为了很好地解释为什么会这样。)AFAIK,每个比IE9更新的浏览器都会自动继承 文档.domain 用于以编程方式创建的iframe,因此这是IE9特有的。由于我的场景有一些独特的需求(tldr:iframesrc需要更改),上面文章中的答案对我不起作用。

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

    我在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粘贴到地址栏中,则页面加载良好,并且如预期的那样为空白。
    • 我尝试过添加 X-Frame-Options SAMEORIGIN 服务器的响应头,如建议 here ,但无济于事。

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

    [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
    



    更新

    我已经确定,它无法开箱即用的原因是应用程序集 文档.domain 在页面加载时,它与(的子集)不同 location.host .FineUploader的303重定向机制运行良好,但 文档.domain iframe的与父级不同(由于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();
            }
        });
    }
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Community Tales Farias    7 年前

    (如果有人在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>
    

    这为我提供了一种方法 document.domain 生成iframe时父页的值。对FineUploader配置对象进行了轻微修改:

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

    这似乎不会干扰AWS预先准备的论点。我们仍然在这个应用程序中使用FineUploader 4.0.3,但这应该也适用于最新版本。

    太长,读不下去了 它起作用了!在IE11文档模式和原生IE9中测试。

        2
  •  1
  •   Ray Nicholus    10 年前

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