大屏展示,开机自启浏览器、自动全屏、绕过验证码自动登录、奔溃自动重启

874 阅读4分钟

老板要在公司大屏显示器上全屏展示监控页面。

于是每天早上去公司第一件事就是把大屏开机并手动登录手动全屏。可是有时候老板去的比我早,发现大屏没开,被老板说这个简单的东西都实现不了。当然可以。

自动开关机

开始研究电脑的自动开关机。电脑设置每天自动开机(手把手教你设置电脑自动开关机) - 路途号 (lutu88.com)

开机自动启动浏览器

开机自动启动浏览器并携带账号密码。win10开机自启动浏览器,打开指定网页_自招的博客-CSDN博客_开机启动浏览器指定网页

还算比较很顺利。网上都能找到设置方法。

绕过验证码

接下来绕过验证码,登录时不传验证码,传一串机器码,保证这个码是唯一的。服务端设置白名单,将机器码放入白名单。如果机器码在白名单中,则绕过验证码校验。

机器码可以有很多方式生成,我们使用的fingerprint2.js。

// 获取机器码
function getFingerprint(callback) {
    var excludes = {
        userAgent: true,
        audio: true,
        enumerateDevices: true,
        fonts: true,
        fontsFlash: true,
        webgl: true,
        canvas: true
    }
    Fingerprint2.get({ excludes: excludes }, function (components) {
        var values = components.map(function (component) {
            return component.value;
        });
        var murmur = Fingerprint2.x64hash128(values.join(''), 31);
        callback(murmur);
    });
}

getFingerprint(console.log) // 获取机器指纹码

自动登录

进入登录页面,获取query参数,如果url中携带了账号密码,尝试自动登录。

var searchParams = {} // 用来存query参数
// 获取query参数,存入searchParams
window.location.search.substr(1).split('&').forEach(function name(params) {
    var arr = params.split('=')
    searchParams[arr[0]] = arr[1]
})
if (searchParams.username && searchParams.password) {
    // 登录地址中携带了账号密码,执行自动登录操作
    getFingerprint(function (fingerprint) {
        login({
            username: searchParams.username,
            password: searchParams.password,
            fingerprint: fingerprint
        });
    });
}

自动全屏

首先想到的是document.requestFullScreen()

经过一番折腾,全屏API调用不成功,后来发现好像需要触发事件才可以,于是new Event() 也试了,还是不行。

因为 requestFullScreen 这个方法只能在用户交互或者设备方向改变的时候调用,否则将会失败。requestFullScreen MDN

因为是自动启动的浏览器,没有用户事件,浏览器端js肯定是解决不了这个问题了。

最终选用VB脚本,可以直接运行在windows。

可以使用vb脚本模拟 F11按键来全屏,也可以使用Chrome提供的启动参数 --start-fullscreen 来全屏启动。因为大屏纯展示,没有用户操作,所以最终选用添加启动参数 --kiosk 以演示模式启动。

Dim delayer
Set delayer = CreateObject("WScript.Shell")
WScript.sleep 8000 ' 等待8s

Dim username
username = "用户名"

Dim password
password = "密码!"

Dim browser
browser = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"

Dim env
env = "http://xxx.com" ' 域名

' 全屏启动浏览器
delayer.run """" + browser + """ -kiosk " + env + "/login.html?_=" & DateDiff("s", #1/1/1970#, Now()) & "&username=" + username + "&password=" + password,0,FALSE

Set delayer = Nothing
WScript.quit

全屏启动搞定

奔溃自动重启

因为机器配置很低,32位操作系统2G内存。跑着跑着页面就奔溃了。只在这个机器上可以复现。最终经过长时间的跟踪发现是不停的追加DOM元素导致的内存溢出。问题解决后奔溃的概率小了很多,但还是会出现。

找问题优化的同时,也考虑怎么最快的发现奔溃并恢复。

最终采用心跳的方式,监测浏览器是否正常运行,30s无响应就重新执行VBScript启动浏览器。

// 浏览器端
// 确保本地存在心跳服务后,持续发起心跳请求
fetch('http://localhost:3000/heartbeat').then(() => {
    // 浏览器端每隔10s发送一次请求
    setInterval(() => {
        fetch('http://localhost:3000/heartbeat')
    }, 10 * 1000)
}).catch(console.log)
// 服务端代码
const express = require('express')
const cmd = require('node-cmd')

const app = express()

let i = 0
setInterval(() = {
    if (i++ >= 30) {
        // 30s无心跳,重新启动浏览器
        cmd.run('./startBrowser.vbs')
        i = 0
    }
}, 1000)

app.use((request, response, next ) => {
    response.header( 'Access-Control-Allow-Origin' , '*')
    next()
})

app.get('/heartbeat', function (req, res) {
    i = 0
    res.send('ok')
})

app.listen(3000, function () {
    console.log('server running, port 3000')
})

将 vbs 脚本和nodejs脚本放入指定文件夹。确保拥有node运行环境。

开机启动项更改为如下脚本

' start.vbs
Set ws = CreateObject("WScript.Shell")
ws.Run "C:/xxx/node.exe C:/desktop/show/main.js",0

最终完成老板的需求。奔溃问题没有彻底解决,持续跟进中(老板给买的机器配置太低了)。奔溃后的及时重启给加了一层保障。机器码可以使用别的更好的方式,用fingerprint2.js 生成的指纹码更新浏览器版本就会改变,也可以跟账号密码一样从url带过来。心跳监测也可以用websocket持久连接,可以更及时的发现奔溃问题。


如有不足,还请指教。欢迎讨论交流。