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

Javascript SecurityError:阻止具有原点的帧访问跨原点帧,javascript,jquery,security,iframe,same-origin-policy,Javascript,Jquery,Security,Iframe,Same Origin Policy,我正在我的HTML页面中加载一个,并尝试使用Javascript访问其中的元素,但当我尝试执行代码时,出现以下错误: SecurityError:阻止了具有原点的帧”http://www..com“从访问交叉原点帧。 你能帮我找到一个解决方案,这样我可以访问框架中的元素吗 我使用此代码进行测试,但徒劳: $(document).ready(function() { var iframeWindow = document.getElementById("my-iframe-id").co

我正在我的HTML页面中加载一个
,并尝试使用Javascript访问其中的元素,但当我尝试执行代码时,出现以下错误:

SecurityError:阻止了具有原点的帧”http://www..com“从访问交叉原点帧。
你能帮我找到一个解决方案,这样我可以访问框架中的元素吗

我使用此代码进行测试,但徒劳:

$(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!";
    });
});
同一原产地政策 您不能使用JavaScript访问不同来源的
,如果您可以这样做,这将是一个巨大的安全漏洞。对于浏览器,阻止脚本尝试访问具有不同原点的帧

如果地址的以下部分中至少有一部分未保留,则认为来源不同:

protocol://hostname:port/... 变通办法 即使同源策略阻止脚本访问具有不同来源的站点的内容,如果您拥有这两个页面,您可以使用及其相关的
消息
事件
来解决此问题,以便在这两个页面之间发送消息,如下所示:

  • 在主页中:

    const frame = document.getElementById('your-frame-id');
    frame.contentWindow.postMessage(/*any variable or object here*/, 'http://your-second-site.com');
    
    window.addEventListener('message', event => {
        // IMPORTANT: check the origin of the data! 
        if (event.origin.startsWith('http://your-first-site.com')) { 
            // The data was sent from your site.
            // Data sent with postMessage is stored in event.data:
            console.log(event.data); 
        } else {
            // The data was NOT sent from your site! 
            // Be careful! Do not use it. This else branch is
            // here just for clarity, you usually shouldn't need it.
            return; 
        } 
    }); 
    
    postMessage()
    的第二个参数可以是
    '*'
    ,以指示对目标的来源没有偏好。在可能的情况下,应始终提供目标来源,以避免泄露您发送到任何其他站点的数据

  • 在您的
    (包含在主页中)中:

此方法可以在两个方向上应用,也可以在主页中创建侦听器,并从框架接收响应。同样的逻辑也可以在弹出窗口中实现,基本上也可以在主页生成的任何新窗口中实现(例如使用),没有任何区别

在浏览器中禁用同源策略 关于这个主题已经有一些很好的答案(我刚刚发现他们在谷歌上搜索),因此,对于可能的浏览器,我将链接相关的答案。但是,请记住,禁用同源策略只会影响浏览器。此外,在禁用同源安全设置的情况下运行浏览器会授予任何网站对跨源资源的访问权限,因此这是非常不安全的,如果您不确切知道自己在做什么(例如开发目的),则不应这样做

  • Microsoft Edge:

补充了Marco Bonelli的答案:当前帧/iFrame之间交互的最佳方式是使用,

检查域的web服务器以获取
http://www..com
X-Frame-Options的配置 它是一种旨在防止点击劫持攻击的安全功能

点击劫持是如何工作的?
  • 邪恶页面看起来与受害者页面一模一样
  • 然后它诱骗用户输入用户名和密码
  • 从技术上讲,邪恶有一个
    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>
    
    问题的解决办法
    如果web服务器激活了安全功能,可能会导致客户端安全错误。

    对我来说,我想实现双向握手,意思是:
    -父窗口的加载速度将快于iframe
    -iframe应在准备就绪后立即与父窗口对话
    -父级已准备好接收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","*");
        }
    });
    
    家长

    $(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);
    });
    
    当然,您可以限制来源和文本,这很容易使用代码
    我发现这个例子很有帮助:

    • 打开“开始”菜单
    • 键入windows+R或打开“运行”
    • 执行以下命令

    chrome.exe--user data dir=“C://chrome-dev-session”--禁用web安全性

    我想添加Java Spring特定的配置,可以对其产生影响

    在网站或网关应用程序中,存在contentSecurityPolicy设置

    在Spring中,您可以找到WebSecurityConfigureAdapter子类的实现

    contentSecurityPolicy("
    script-src 'self' [URLDomain]/scripts ; 
    style-src 'self' [URLDomain]/styles;
    frame-src 'self' [URLDomain]/frameUrl...
    


    如果您没有在此处定义安全的外部contenet,浏览器将被阻止。

    如果您可以控制iframe的内容,也就是说,如果它仅在跨源设置中加载,例如在Amazon Mechanical Turk上,您可以使用内部html的
    属性来避免此问题

    例如,对于内部html,使用
    this
    html参数(定义了yes-
    this
    ,它引用内部主体元素的父窗口):

    在内部html中:

        function changeForm(window) {
            console.log('inner window loaded: do whatever you want with the inner html');
            window.document.getElementById('mturk_form').style.display = 'none';
        </script>
    
    函数更改表单(窗口){
    log('加载的内部窗口:使用内部html执行任何操作');
    window.document.getElementById('mturk_form')。style.display='none';
    
    我在尝试嵌入iframe,然后用Brave打开站点时遇到了这个错误。当我改为“关闭屏蔽”时,错误消失了"对于有问题的网站。显然,这不是一个完整的解决方案,因为任何其他带着Brave访问网站的人都会遇到同样的问题。要真正解决这个问题,我需要做本页列出的其他事情之一。但至少我现在知道了问题所在。

    我找到的任何其他答案都表明CORS/
    访问控制ol Allow Origin
    不适用于iframe,仅适用于。我相信
    postMessage
    是唯一的选项。@ccppjava您不需要==,您已经知道变量类型它是字符串,所以===在这里是无用的。@SABAHANG只需检查
    iframe.src
    ,如果站点的主机名与域的主机名不同,您就可以使用它无法访问该帧。@user2568374这是一个糟糕的主意。如果您检查
    event.origin.indexOf(location.ancestorOrigins[0])
    您是
    .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
    
        function changeForm(window) {
            console.log('inner window loaded: do whatever you want with the inner html');
            window.document.getElementById('mturk_form').style.display = 'none';
        </script>