Web端切屏检测的实现和反制手段

目录:前端开发  |  发表于:2024-06-20 21:10:31

Web端的考试系统中,为了防止考生用电脑切到其他页面或软件查资料,一般都会在考试时进入全屏并设置切屏检测功能。这篇文章介绍如何实现类似的全屏和切屏检测,以及如何破解切屏检测。

实现切屏检测

实现切屏检测其实很简单,我们切屏时都会造成窗口失去焦点,浏览器JavaScript中也有对应的API来判断当前页面是否失去焦点。

下面例子中我们编写了一个简单的页面,点击「开始考试」按钮后,系统会进入全屏状态且监听window对象的blur事件,页面失去焦点时对应的事件函数会被回调。

index.html

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>考试系统</title>
    <script src="jquery.min.js"></script>
    <script src="index.js"></script>
  </head>
  <body>
    <button id="begin-exam">开始考试</button>
    <div id="msg-box"></div>
  </body>
</html>

index.js

$(function () {
  function launchFullscreen(element) {
    if (element.requestFullscreen) {
      element.requestFullscreen();
    } else if (element.mozRequestFullScreen) {
      element.mozRequestFullScreen();
    } else if (element.webkitRequestFullscreen) {
      element.webkitRequestFullscreen();
    } else if (element.msRequestFullscreen) {
      element.msRequestFullscreen();
    }
  }

  $("#begin-exam").click(function () {
    launchFullscreen(document.documentElement);
    window.addEventListener("blur", function () {
      $("#msg-box").append(
        "<div>[" +
          new Date().toLocaleTimeString() +
          "]你切屏了,考试中禁止切屏!</div>"
      );
    });
  });
});

当我们切屏时系统就会给出警告。

实际上,除了window对象的blur,我们还有一些其它可以监听的位置来判断是否发生了切屏,例如document对象的mouseleave等。

破解切屏检测

破解切屏检测比较Low但绝对可靠的方式是使用虚拟机,不过虚拟机启动后比较耗系统资源,有些情况下我们也不方便在考试电脑上安装虚拟机软件和里面的操作系统。

实际上,在浏览器中破解切屏检测也十分容易,我们将blurmouseleave等事件的回调函数覆盖掉即可,此外为了将脚本注入到页面,我们可以使用油猴插件来实现。

具体例子代码如下。

// ==UserScript==
// @name         Fuck Examination
// @namespace    http://tampermonkey.net/
// @version      2024-06-20
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function () {
  "use strict";
  Object.defineProperty(window, "onblur", {
    value: null,
    writable: false,
  });
  Object.defineProperty(document, "onblur", {
    value: null,
    writable: false,
  });
  Object.defineProperty(window, "onmouseleave", {
    value: null,
    writable: false,
  });
  Object.defineProperty(document, "onmouseleave", {
    value: null,
    writable: false,
  });
  Object.defineProperty(window, "onvisibilitychange", {
    value: null,
    writable: false,
  });
  Object.defineProperty(document, "onvisibilitychange", {
    value: null,
    writable: false,
  });

  const originalEventTargetAddEventListener =
    EventTarget.prototype.addEventListener;
  const originalHTMLElementAddEventListener =
    HTMLElement.prototype.addEventListener;
  const originalWindowAddEventListener = Window.prototype.addEventListener;
  const originalDocumentAddEventListener = Document.prototype.addEventListener;

  function allowCall(eventName) {
    return (
      eventName !== "visibilitychange" &&
      eventName !== "focus" &&
      eventName !== "focusin" &&
      eventName !== "focusout" &&
      eventName !== "blur" &&
      eventName !== "mouseleave"
    );
  }

  EventTarget.prototype.addEventListener = function (eventName, eventHandler) {
    if (allowCall(eventName)) {
      originalEventTargetAddEventListener.call(this, eventName, eventHandler);
    }
  };

  HTMLElement.prototype.addEventListener = function (eventName, eventHandler) {
    if (allowCall(eventName)) {
      originalHTMLElementAddEventListener.call(this, eventName, eventHandler);
    }
  };

  Window.prototype.addEventListener = function (eventName, eventHandler) {
    if (allowCall(eventName)) {
      originalWindowAddEventListener.call(this, eventName, eventHandler);
    }
  };

  Document.prototype.addEventListener = function (eventName, eventHandler) {
    if (allowCall(eventName)) {
      originalDocumentAddEventListener.call(this, eventName, eventHandler);
    }
  };
})();

启用插件脚本后,前面编写的切屏检测代码就不再起作用了。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap