JS 关闭浏览器或关闭该网页所有相关的Tab页,再次访问则需要重新登录,刷新不影响

148 阅读2分钟
  • 最近有个安全需求,当关闭浏览器的时候,再次访问网页需要重新登录,如果当前浏览器中没有一个 tab 标签页存在访问该网页的情况下,进行访问也需要重新登录,但是刷新则不受影响不需要重新登录,

  • secure.js 使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <script src="./secure.js"></script>
    </head>
    <body>
      <script>
        // 测试登录状态
        alert(secure.isLogin())
    
        // 案例代码
        // if (secure.isLogin()) {
        //  // 退出登录
        //  logout()
        //  // 可能会刷新页面失败导致没有进入登录页面,所以异步或延迟刷新页面达到进入登录页的效果
        //  setTimeout(() => {
        //    window.location.reload();
        //  }, 0)
        // }
      </script>
    </body>
    </html>
    
  • secure.js:导入项目即可

    // 使用案例
    // <script>
    //   // 案例代码
    //   if (secure.isLogin()) {
    //    	// 退出登录
    //     logout()
    //    	// 可能会刷新页面失败导致没有进入登录页面,所以异步或延迟刷新页面达到进入登录页的效果
    //     setTimeout(() => {
    //       window.location.reload();
    //     }, 0)
    //   }
    // </script>
    
    // 安全管理对象
    const secure = {
      // 唯一键,用于标识当前网站的页面数量
      siteKey: 'secure-statistical-tabs',
      // 页面标识符(随机生成唯一ID)
      pageId: Math.random().toString(36).slice(2, 11),
      // 是否已经初始化了
      isInitTabs: false,
      // 需要登录
      isLogin () {
        // 添加页面标识
        this.initTabs()
        // 获取页面标识
        const tabs = this.getTabs()
        // 只有一个页面标识 && 从首次访问该网页
        if (tabs.length === 1 && this.isTabFirstVisit()) {
          return true
        } else {
          return false
        }
      },
      // 初始化页面标识符
      initTabs () {
        // 以防重复调用
        if (this.isInitTabs) { return }
        this.isInitTabs = true
        // 页面卸载时移除当前页面标识
        window.addEventListener('beforeunload', () => {
          // 移除当前页面ID
          const tabs = this.getTabs().filter(id => id !== this.pageId)
          // 更新
          localStorage.setItem(this.siteKey, JSON.stringify(tabs))
        })
        // 监听 localStorage 变化,检查当前页面数量
        // window.addEventListener('storage', () => {
        //   const tabs = JSON.parse(localStorage.getItem(this.siteKey) || '[]')
        //   console.log(`当前打开的同一网站页面数量:${tabs.length}`)
        // })
        // 初始化时调用
        this.updateTabs()
      },
      // 是否在Tab中首次访问该网页
      isTabFirstVisit () {
        // 老版本:performance.navigation.type
        // performance.navigation.TYPE_NAVIGATE: 值为 0,页面是通过常规的导航方式加载的。这包括首次访问页面、通过点击链接、表单提交等方式进入页面。
        // performance.navigation.TYPE_RELOAD: 值为 1,页面是通过用户手动刷新(如按下刷新按钮或按 F5 键)或通过 JavaScript 的 location.reload() 方法重新加载的。
        // performance.navigation.TYPE_BACK_FORWARD: 值为 2,页面是通过浏览器的“前进”或“后退”按钮加载的。
        // performance.navigation.TYPE_RESERVED: 值为 255,这个值是保留的,通常不会被使用。
        // return performance.navigation.type === performance.navigation.TYPE_NAVIGATE
    
        // 新版本:PerformanceNavigationTiming
        // "navigate": 页面通过常规的导航方式(如链接或输入 URL)加载。
        // "reload": 页面是通过刷新(手动刷新或 location.reload())加载。
        // "back_forward": 页面是通过浏览器的“前进”或“后退”按钮加载。
        // "prerender": 页面是通过预渲染过程加载(例如,使用了浏览器缓存或其他预加载技术)。
        const [navigationEntry] = performance.getEntriesByType('navigation')
        return navigationEntry.type === 'navigate'
      },
      // 获取页面标识符
      getTabs () {
        // 获取
        const tabs = JSON.parse(localStorage.getItem(this.siteKey) || '[]')
        // 返回
        return tabs
      },
      // 每次新加载页面时更新页面ID
      updateTabs() {
        // 获取页面标识
        const tabs = this.getTabs()
        // 是否包含
        if (!tabs.includes(this.pageId)) {
          // 添加
          tabs.push(this.pageId)
          // 更新
          localStorage.setItem(this.siteKey, JSON.stringify(tabs))
        }
      }
    }