跨框架跨站点脚本-创建网页重载程序/看门狗

Cross-frame cross-site scripting - creating a webpage reloader/watchdog

本文关键字:重载 程序 看门狗 网页 创建 框架 站点 脚本      更新时间:2023-09-26

设置:

有远程测量站,有集中的收集/处理/呈现服务器(带网络服务器(,还有观测站,为客户显示收集的数据。

这些观测站由简单的嵌入式计算机组成,该计算机配备了以信息亭模式工作的网络浏览器,每个浏览器显示来自中央服务器的一个特定网页。此网页使用AJAX进行更新,显示给定测量站的最新测量结果。连接到一个固定的监视器,这些工作站应该可以在几年内几乎免费运行。

现在我们已经解决了大部分问题,但问题是:如果网络服务器出现故障怎么办?浏览器将加载"无法访问"、"404"、"权限被拒绝"、"500"或服务器当时发生的任何故障模式,并一直保持在那里,直到有人手动重新启动观测站。

我想出的一般解决方案是,将浏览器的主页不是设置为观察到的页面,而是设置为始终可用的本地HTML文件,如果远程页面加载和更新正确,该文件将执行定期检查,如果由于任何原因无法执行,则重新加载。

问题:

问题在于跨框架脚本。我想目标网页必须加载为框架、iframe、text/HTML类型的对象,或者其他一些方式,使其在不删除/禁用本地"容器"文件的情况下显示。几年前,我写了一个跨框架脚本页面,规避安全对策并不容易。从那时起,安全措施一定加强了。

因此,从远程服务器加载的页面包含一段javascript,如果一切顺利,它会定期启动(一些setInterval(,如果出现问题,则不会启动。该信号周期性地到达容器帧使其重置超时并且不采取任何其他操作。

在信号没有到达的情况下,随着超时到期,容器开始定期刷新加载的网页,直到服务器被修复并加载了适当的内容,向加载器发出信号。

每次触发特定函数时,我如何让远程页面向从文件加载的本地(容器(页面发出"活动"信号(比如设置变量(://URL?

有一个名为porthole的库,它基本上做SF的事情我只是写了一个网页来切换显示两个iframe中的一个。在顶级网页中,我有

var windowProxy;
windowProxy = new Porthole.WindowProxy(baseURL + '/porthole/proxy.html', frameId);
windowProxy.addEventListener(onMessage);
...
function onMessage(messageEvent) {
    if (messageEvent.origin !== baseURL) {
        $log.error(logPrefix + ': onMessage: invalid origin');
        console.dir(messageEvent);
        return;
    }
    if (messageEvent.data.pong) {
        pongReceived();
        return;
    }
    $log.log(logPrefix + ': onMessage: unknown message');
    console.dir(messageEvent);
}
...
var sendPing = function () {
    $log.log(logPrefix + ': ping to ' + baseURL);
    ...
    windowProxy.post({ 'ping': true });
};

加上一些附加的控制逻辑。在子网页中,以下是我必须添加的所有内容(加上控制器对portholeService.init()的调用(:

// This service takes care of porthole (https://github.com/ternarylabs/porthole)
// communication if this is invoked from a parent frame having this web page
// as a child iframe. Usage of porthole is completely optional, and should
// have no impact on anything outside this service. The purpose of this
// service is to enable some failover service to be build on top of this
// using two iframes to switch between.
services.factory('portholeService', ['$rootScope', '$log', '$location', function ($rootScope, $log, $location) {
    $log.log('Hello from portholeService');
    function betterOffWithFailover() {
        ...
    }
    function onMessage(messageEvent) {
        $rootScope.$apply(function () {
            if (messageEvent.origin !== baseUrl) {
                $log.error('onMessage: invalid origin');
                console.dir(messageEvent);
                return;
            }
            if (!messageEvent.data.ping) {
                $log.error('unknown message');
                console.dir(messageEvent.data);
                return;
            }
            if (betterOffWithFailover()) {
                $log.log('not sending pong');
                return;
            }
            windowProxy.post({ 'pong': true });
        });
    }
    var windowProxy;
    var baseUrl;
    function init() {
        baseUrl = $location.protocol() + '://' + $location.host() + ':' + $location.port();
        windowProxy = new Porthole.WindowProxy(baseUrl + '/porthole/proxy.html');
        windowProxy.addEventListener(onMessage);
    }
    return {
        init: init
    };
}]);

为了参考,这些页面使用AngularJS,以防$rootScope.$apply等对您不熟悉。

跨框架、跨站点通信的方法是使用postMessage。

包含的帧,在每次正确执行时应执行:

window.top.postMessage('tyrp', '*');

集装箱文件应包含:

window.onmessage = function(e)
{
    if (e.data == 'tyrp') {
        //reset timeout here
    }
};