首页 文章

SecurityError:阻止具有原点的帧访问跨源帧

提问于
浏览
371

我在我的HTML页面中加载 <iframe> 并尝试使用Javascript访问其中的元素,但是当我尝试执行我的代码时,我收到以下错误:

SecurityError: Blocked a frame with origin "http://www.<domain>.com" from accessing a cross-origin frame.

你能帮我找一个解决方案,以便我可以访问框架中的元素吗?

我正在使用此代码进行测试,但徒劳无功:

$(document).ready(function() {
    var iframeWindow = document.getElementById("my-iframe-id").contentWindow;

    iframeWindow.addEventListener("load", function() {
        var doc = iframe.contentDocument || iframe.contentWindow.document;
        var target = doc.getElementById("my-target-id");

        target.innerHTML = "Found it!";
    });
});

5 回答

  • 5

    同源政策

    不要与CORS混淆!

    can't 使用JavaScript访问具有不同来源的 <iframe> ,如果您可以这样做,那将是一个巨大的安全漏洞 . 对于same-origin policy browsers block scripts trying to access a frame with a different origin .

    如果不维护地址的以下部分中的至少一个,则认为原点不同:

    <protocol>://<hostname>:<port>/path/to/page.html
    

    如果要访问框架, Protocolhostnameport 必须与您的域相同 .

    例子

    以下是尝试从 http://www.example.com/home/index.html 访问以下URL的情况

    URL                                             RESULT 
    http://www.example.com/home/other.html       -> Success 
    http://www.example.com/dir/inner/another.php -> Success 
    http://www.example.com:80                    -> Success (default port for HTTP) 
    http://www.example.com:2251                  -> Failure: different port 
    http://data.example.com/dir/other.html       -> Failure: different hostname 
    https://www.example.com/home/index.html.html -> Failure: different protocol 
    ftp://www.example.com:21                     -> Failure: different protocol & port 
    https://google.com/search?q=james+bond       -> Failure: different hostname & protocol
    

    解决方法

    即使同源策略阻止脚本访问具有不同来源的站点内容, if you own both the pages, you can work around this problem using window.postMessage and its relative message event 也可以在两个页面之间发送消息,如下所示:

    • 在您的主页面中:
    var frame = document.getElementById('your-frame-id'); 
    
    frame.contentWindow.postMessage(/*any variable or object here*/, '*');
    
    • <iframe> 中(包含在主页面中):
    window.addEventListener('message', function(event) { 
    
        // IMPORTANT: Check the origin of the data! 
        if (~event.origin.indexOf('http://yoursite.com')) { 
            // The data has been sent from your site 
    
            // The data sent with postMessage is stored in event.data 
            console.log(event.data); 
        } else { 
            // The data hasn't been sent from your site! 
            // Be careful! Do not use it. 
            return; 
        } 
    });
    

    此方法可以应用于 both directions ,也可以在主页面中创建侦听器,并从帧接收响应 . 同样的逻辑也可以在弹出窗口中实现,并且基本上由主页面生成的任何新窗口(例如,使用window.open())也可以实现,没有任何区别 .

    在浏览器中禁用同源策略

    关于这个主题已经有了一些很好的答案(我只是发现它们谷歌搜索),因此,对于可能的浏览器,我将链接相关的答案 . 但请记住 disabling the same-origin policy (or the CORS) will only affect your browser . 此外,运行具有相同来源安全设置的浏览器会禁止任何网站访问跨源资源,因此 it's very unsafe and should be done for development purposes only .

  • 564

    补充Marco Bonelli的答案:帧/ iframe之间最佳的交互方式是使用window.postMessagesupported by all browsers

  • 9

    检查域的Web服务器 http://www.<domain>.com 配置 X-Frame-Options 这是一个旨在防止clickJacking攻击的安全功能,

    clickJacking如何工作?

    • 邪恶页面看起来与受害者页面完全相同 .

    • 然后它欺骗用户输入他们的用户名和密码 .

    从技术上讲,邪恶有一个 iframe 与受害者页面的来源 .

    <html>
        <iframe src='victim_domain.com'/>
        <input id="username" type="text" style="display: none;/>
        <input id="password" type="text" style="display: none;/>
        <script>
            //some JS code that click jacking the user username and input from inside the iframe...
        <script/>
    <html>
    

    安全功能如何工作

    如果要阻止在 iframe 中呈现Web服务器请求,请添加x-frame-options

    X-Frame-Options DENY

    选项是:

    • SAMEORIGIN //仅允许我自己的域在iframe中呈现我的HTML .

    • 拒绝//不允许我的HTML在任何iframe中呈现

    • “ALLOW-FROM https://example.com/”//允许特定域在iframe中呈现我的HTML

    这是IIS配置示例:

    <httpProtocol>
           <customHeaders>
               <add name="X-Frame-Options" value="SAMEORIGIN" />
           </customHeaders>
       </httpProtocol>
    

    问题的解决方案

    如果Web服务器激活了安全功能,则可能会导致客户端SecurityError .

  • 44

    对我来说,我想实现双向握手,意思是:

    • 父窗口加载速度比iframe快
    • iframe一旦准备就应该与父窗口通话
    • 父级已准备好接收iframe消息并重播

    此代码用于使用[CSS custom property]在iframe中设置白色标签
    码:
    iframe

    $(function() {
        window.onload = function() {
            // create listener
            function receiveMessage(e) {
                document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
                document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
                document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
                //alert(e.data.data.header_bg);
            }
            window.addEventListener('message', receiveMessage);
            // call parent
            parent.postMessage("GetWhiteLabel","*");
        }
    });
    

    parent

    $(function() {
        // create listener
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
        eventer(messageEvent, function (e) {
            // replay to child (iframe) 
            document.getElementById('wrapper-iframe').contentWindow.postMessage(
                {
                    event_id: 'white_label_message',
                    wl: {
                        header_bg: $('#Header').css('background-color'),
                        header_text: $('#Header .HoverMenu a').css('color'),
                        button_bg: $('#Header .HoverMenu a').css('background-color')
                    }
                },
                '*'
            );
        }, false);
    });
    

    当然,你可以限制起源和文本,这是易于使用的代码
    我发现这个考试很有帮助:
    [Cross-Domain Messaging With postMessage]

  • 0

    打开开始菜单
    键入Windows R或打开“运行
    执行以下命令 .

    chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
    

相关问题