首页  >  文章  >  web前端  >  TIL:在 Javascript 中阻止选项卡并获取 IP

TIL:在 Javascript 中阻止选项卡并获取 IP

Linda Hamilton
Linda Hamilton原创
2024-10-31 19:03:02926浏览

欢迎来到我的“今天我学到了”系列的第一部分!通过这些帖子,我将分享我在作为算法工程师的工作中获得的实际见解,深入研究我为解决现实世界挑战而实施的技术。我希望这些课程也能为您的项目带来价值。

要点

  • 控制多个选项卡实例:防止用户打开同一 Web 应用程序的多个实例,这可能会耗尽资源并可能导致服务器崩溃。
  • 使用 JavaScript 获取用户 IP 地址:了解为什么由于安全限制和探索解决方法,在 JavaScript 中获取用户的 IP 地址是一个挑战。

为了说明这一点,我将介绍我所从事的一个涉及人脸识别技术的项目,特别是简化处理和维护跨用户性能所需的步骤。

项目概述:构建人脸识别 Web 应用程序

TIL: Block tabs and Get IP in Javascript

在此示例中,任务是创建一个可通过网络浏览器访问的人脸识别应用程序(签入签出系统)。该应用程序需要:

  1. 页面加载时自动启动。
  2. 捕获用户的脸部,检查“活跃度”(确认其是真人),然后将图像传输到服务器进行识别。
  3. 在浏览器上显示识别结果。

该应用程序设计有两个主要组件:

  • 客户端处理:包括人脸检测和活体检测,在浏览器中处理。
  • 服务器端处理:负责人脸识别,利用服务器资源进行身份匹配。

为了简单起见,假设客户端在将其发送到服务器之前检测并验证脸部,服务器返回结果,浏览器显示它们。

问题:防止多个选项卡

TIL: Block tabs and Get IP in Javascript

想象一下一个典型的用户 Alex,他最近开始使用新的面部识别网络应用程序来上班和下班。一天早上,亚历克斯决定在几个浏览器选项卡中打开该应用程序,认为他可以通过同时在多个选项卡中测试它来加快签入速度。

几乎立刻,事情就开始走下坡路。加载每个选项卡时,它会独立初始化应用程序的面部检测和验证过程。亚历克斯注意到他的计算机速度急剧下降,最终,浏览器开始滞后。在幕后,这些多个选项卡均使用资源来处理 Alex 的脸部,这对他的设备性能造成了巨大损失。

但问题并没有就此结束。由于每个选项卡向服务器发送单独的识别请求,应用程序的服务器负载激增,导致其他用户同时登录出现延迟。服务器因重复请求而不堪重负,几乎无法跟上,导致延迟和错过签到。

为了让事情变得更加混乱,每个选项卡都显示不同的、不一致的登录状态。 Alex 很快意识到,在多个选项卡中打开应用程序给他带来了不必要的麻烦,并给整个公司带来了潜在的问题。

为了确保无缝功能并避免对客户端和服务器资源造成不必要的压力,我们需要防止用户使用应用程序打开多个选项卡

目标是限制用户在浏览器中一次打开多个应用程序实例,主要是通过检测同一应用程序的其他选项卡何时已打开。解决方法如下:

if (localStorage.getItem('isAppRunning') === 'true') {
    alert("The application is already open in another tab. Please close this tab.");
} else {
    // Set a flag in localStorage to indicate the app is running
    localStorage.setItem('isAppRunning', 'true');

    // Add an event listener to clear the flag when the tab is closed
    window.addEventListener('beforeunload', () => {
        localStorage.removeItem('isAppRunning');
    });

    // Main function to load models and start video if the app is not running in another tab
    (async function main() {
        try {
            const config = await loadConfig(); // Load models concurrently

            const [tinyFaceDetector, fasnet, phoneDetect] = await Promise.all([
                loadTinyFaceDetector(),
                loadFasnet(config),
                loadPhoneDetect(config),
            ]);
            Object.assign(window, { fasnet, phoneDetect, config });

            startVideo();
        } catch (err) {
            console.error('Initialization failed:', err);
        }
    })();
}

问题:获取用户IP

在我们的人脸识别系统中,要求已发展为仅允许授权的部门特定访问。例如,如果人员 A 属于部门 A,则他们应该只能在部门 A 网络中的设备上签入或签出,而不能在部门 B 或任何其他部门的设备上签入或签出。由于这些计算机是通过局域网 (LAN) 连接的,因此我们需要一种方法来根据设备的 IP 地址来识别和限制访问

TIL: Block tabs and Get IP in Javascript

当我在网上搜索时,我得到了一些有关获取IP地址的信息。但他们有一些问题

function user_location() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      console.log( this.responseText);
    }
  };
  xhttp.open("GET", "//api.ipify.org?format=json", true);
  xhttp.send();
}

该函数成功获取用户的公网IP地址;但是,它不提供部门特定访问控制所需的内部 LAN IP 地址。此外,它还容易受到 VPN 或防火墙的屏蔽。

或者也许是这个

Firefox 和 Chrome 已经实现了 WebRTC,允许向 STUN 服务器发出请求,该服务器将返回用户的本地和公共 IP 地址

但我不想在我的应用程序中添加更多包。这种复杂性,再加上潜在的跨浏览器不一致,使其不太理想。

然后我发现了这篇文章

使用浏览器中运行的 JavaScript 直接检索客户端 IP 地址并不简单。这是因为 JavaScript 无法访问暴露 IP 地址的网络层。此外,出于安全原因,浏览器对 JavaScript 环境进行沙箱处理,阻止其访问某些系统级信息,包括客户端的 IP 地址。

事实证明,仅使用 JavaScript 检索 IP 地址是不可行的。不过,有一个简单的解决方案:在服务器上创建 API 端点来获取用户的 IP 地址。

if (localStorage.getItem('isAppRunning') === 'true') {
    alert("The application is already open in another tab. Please close this tab.");
} else {
    // Set a flag in localStorage to indicate the app is running
    localStorage.setItem('isAppRunning', 'true');

    // Add an event listener to clear the flag when the tab is closed
    window.addEventListener('beforeunload', () => {
        localStorage.removeItem('isAppRunning');
    });

    // Main function to load models and start video if the app is not running in another tab
    (async function main() {
        try {
            const config = await loadConfig(); // Load models concurrently

            const [tinyFaceDetector, fasnet, phoneDetect] = await Promise.all([
                loadTinyFaceDetector(),
                loadFasnet(config),
                loadPhoneDetect(config),
            ]);
            Object.assign(window, { fasnet, phoneDetect, config });

            startVideo();
        } catch (err) {
            console.error('Initialization failed:', err);
        }
    })();
}
  • 当客户端发出请求时,Flask 会自动使用各种标头和连接详细信息填充请求对象。

  • 首先,代码使用 client_ip = request.headers.get('X-Forwarded-For') 检查 X-Forwarded-For 标头。

  • 用途:此标头通常由代理或负载均衡器设置,以保留原始客户端 IP 地址。如果请求通过代理或负载均衡器传递,则客户端的实际 IP 地址应出现在此标头中。

  • 如果找到 X-Forwarded-For 标头,client_ip 将设置为其值。

  • 如果 X-Forwarded-For 标头丢失(例如,如果客户端在没有代理的情况下直接连接),则代码使用 request.remote_addr 直接从客户端获取 IP 地址。

概括

在这篇文章中,我分享了我在开发基于网络的人脸识别应用程序时应对现实世界挑战的经验。以下是我们解决的两个关键问题:

  • 防止多个选项卡实例:为了阻止用户在多个浏览器选项卡中打开应用程序,我们使用 localStorage 来跟踪应用程序是否已打开。这可以防止冗余的人脸检测过程对客户端和服务器资源造成压力。

  • 检索用户 IP 地址:由于安全限制,JavaScript 无法直接访问设备的 LAN IP,因此我们在服务器上设置 API 端点以从请求标头中获取 IP。这种方法确保仅对授权设备进行部门特定的访问控制。

以上是TIL:在 Javascript 中阻止选项卡并获取 IP的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn