点赞
评论
收藏
分享
举报
看完怒涨薪资30k?同一浏览器只允许登录一个账号的解决办法(Vue单页)
发表于2021-12-13 15:56

浏览 1.1k

文章标签

相同浏览器只允许登录一个账号的需求相信是很多前端小伙伴的面临过或者将要面临的问题,看似没有什么大问题的问题,其实有点东西的。这里介绍一下我尝试多种办法之后得出的一个最优的解决办法


情况一

当窗口一登录了admin账号,再去复制项目里面的地址用窗口二打开

注意这里是项目里面的地址,有点东西的地方在于登录地址,下面再介绍,且看: 窗口二打开任意一个项目里面的地址我们要的效果都是可以直接访问的(各大bat的产品也是这样的效果,毋庸置疑)。那么我们是怎么做到当窗口一登录了之后,其他窗口可以访问项目里面的任意地址,而当没有窗口登录,复制项目里面的地址不能访问(安全问题)让其跳转到登录页 上代码:我们在main.js里面


router.beforeEach((to,from,next) => { //这里是在所有路由跳转之前都会去执行以下操作
  if(to.path == '/'){ //如果要去的是登录页
    next() //那么随意,去就是了
  } else { //如果不是
    if(localStorage.getItem('isLogin')){ //判断当前浏览器的本地存储里面是不是有已经登录的信息
      next() //有的话,ok,去你想去的地址
    } else { //没有的话,也就是没有登录
      next({path:'/'}) //去登录页
    }
  }
})
复制代码


这里的isLogin是我自己命名在login.vue的登录的时候存进去本地的,当然也可以存接口返回的user信息,whatever you like


// 登录按钮执行登录的时候,至于为什么存localStorage,不用sessionStore,自行百度其中的区别,相信你会明了的
localStorage.setItem("isLogin", 1)
复制代码


这里要注意,在退出按钮的时候要执行清除登录状态的操作,否则本地存储会一直保留(不手动清缓存的情况下)


// 执行退出登录操作的时候执行
localStorage.removeItem("isLogin")
复制代码


到这里应该都没有什么问题,都是常规操作 >o<!


情况二

当窗口二去到登录页面,并且登录了另一个非admin的账号

这种情况下,我们是不是要把窗口一的admin的账号覆盖掉?是的,可能菜单权限不一样,页面风格都不一样的情况下,我们怎么去覆盖这个页面所展示的信息?
刚开始我的想法是监听浏览器的窗口切换,再次切回窗口一的时候再次点击页面上的某处去执行接口请求的时候刷新页面,这是有逻辑上的问题的,因为我们并不能检测到页面是否有接口请求,只能接测到是否有路由跳转,但是页面上只有一部分比如菜单点击才有路由跳转,所以这个方法是有问题的。(这段废话是为了更好的表明我的思路emmmm......)


换种思路!要实现这个逻辑,我们就必须要检测到浏览器是否有新窗口执行了账号登录,也就是监测浏览器的本地存储是否有东西,vue的watch监测并不能监测非vue机制存放的数据(这句话我在上一篇文章中也提过),也就是说watch不能实时监测localStorage里面的数据,而我们或许会想到把localStorage里面的数据在保存到vuex里面去达到实时监测的效果,但是,vuex会在其他窗口登录的时候被重置,但是这个思路是对的!!!直接说我怎么实现的:


手动去创建一个js文佳再在里面创建一个全局变量export出去,把这个全局变量创建在一个单独的文件中,然后再去组件里面引用,这个全局变量是能被watch监测


要做到这个全局变量不被其他窗口的登录给重置掉,这里就是个小心思了


在登陆组件login.vue里面引入这个全局变量,在登陆按钮执行成功的时候去赋值,主要看带注释的地方


// login.vue先引入
import global from '@/config/common.js'
methods: {
  login () {
    if (this.user == '') {
          this.$message.error('账号不能为空!');
        } else if (this.password == '') {
          this.$message.error('密码不能为空!');
        } else {
          this.setCookie(this.user)
          this.$post('/api/manage/user/login.json', {
            userName: this.user,
            passWord: this.$md5(this.password)
          }).then(res => {
              localStorage.setItem("isLogin", 1)
              global.aaa = res.obj.id //这里才是登录成功的时候去赋值,我是创建的 aaa 这个变量为例子
              localStorage.setItem('userId', res.obj.id) // 同时也要做的是将这个用户id存进localStorage
              this.$router.push({path: '/container'})
            })
            .catch(err => {
              this.$message.error(err.msg)
            })
        }
      }
  }
复制代码


那我们登录成功之后会在本地代码里面保存这个用户id,也在浏览器的localStorage里面保存了一份,接着,在main.js里面


import global from '@/config/common.js'


window.addEventListener("visibilitychange",function(){ //这个方法是监测浏览器窗口发生变化的时候执行
  if (document.hidden == false && global.aaa != localStorage.getItem('userId')) {
    global.aaa = localStorage.getItem('userId') //只有当初始创建的aaa不等于localStorage里面的userId的时候去覆盖掉这个aaa
  }
  //不覆盖的话aaa永远都是我们设的初始值
});
复制代码


最后,我们在app.vue里面去监听这个全局变量的变化


watch: {
    'global.aaa' : 'refresh'
  },
methods: {
   refresh () {
  //执行刷新操作,这里我没有写this.$route.go(0),因为整个页面抖动不是很友好
  //现将app.vue下面的 头部组件,菜单组件,内容组件隐藏再放出来,实现刷新一样的效果
        this.hackReset = false
        this.$nextTick(() => {
          this.hackReset = true
        })
      }
}
复制代码


好了,在第二个窗口登录另一个账号,返回第一个窗口的时候,改窗口登了的账号被挤掉,整个页面同步到第二个窗口所登录的账号信息,这个效果实现了!!!代码倒是没有什么很高深的要写,只是思路很重要,有点曲折,实现完功能发现,头发又掉了好几根。


结束语

本文提供作者:蜗牛先笙
原贴地址:www.jianshu.com/p/89b0c29cb…
觉得文章写的好,请给戳↑链接关注作者,给文章点个赞嗷~
摸鱼学习交流请戳:shimo.im/sheets/CtcH…

已修改于2023-03-09 02:20
创作不易,留下一份鼓励
好文分享者

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
好文分享者
这家伙很懒还未留下介绍~
2
文章
0
问答
1
粉丝
相关文章
前言大家平时在工作中,或多或少应该接触过微信鉴权登录,获取用户信息的相关需求。也有小伙伴经常会在群里问一些相关的问题,比如鉴权登录的整体流程是什么?整个流程里面,前端和后端的分工是什么?前端专门准备了一个鉴权回调页面,要怎么回到鉴权前的页面?怎么在本地测试微信网页授权?先看看微信官方的鉴权流程怎么描述的第一步:用户同意授权,获取code第二步:通过code换取网页授权access_token第三步:刷新access_token(如果需要)第四步:拉取用户信息(需scope为snsapi_userinfo)还是懵,没关系,我在这里专门准备了一个小🌰,来实现了一套简易版的网页授权+获取用户信息的功能,整个流程大概是这样的在这个流程中,前端不用做太多事,只需要判断有没有用户信息,如果没有,剩下的事情交给服务端,等服务端全部处理完成,会带着用户信息,返回之前的页面。并且前端无需准备专门的授权结果页。流程第一步:内网映射下载软件下载地址:ngrok.com/download解压出来之后是这个东西终端启动将解压出来的文件拖到终端中,紧接着写http3000,意思就是用ngrok在3000端口上
点赞 0
浏览 1.1k
目录问题背景解决思路网络拓扑搭建Macvlan命名空间测试命名空间网络连通性启动nginx服务结语1、问题背景  一种多租户多Nginx集群部署的上云解决方案示意图如图1所示:图1一种多租户多Nginx集群部署示意图  该方案主要包含三部分,分别为APIServer,配置中心及集群部署节点,各部分实现的功能为:APIServer:Nginx集群服务的总入口,负责接收各类管控信息,并将请求信息解析后转发至配置中心;配置中心:负责不同租户Nginx实例的安装部署与配置管理;集群部署节点:不同租户在不同节点上部署Nginx实例,实现实例级别的高可用;  如图1所示,要实现高可用的部署方式,就要求在每一个服务器node节点上部署的Nginx实例分属于不同的租户;要实现每个node节点的Nginx实例分属于不同的租户,就要求在node节点实现租户隔离。这里的租户隔离至少需要包含两个属性,一个是网络资源的隔离,一个是Nginx实例端口占用的隔离。2、解决思路为了在同一台node节点实现租户隔离,目前常见的有以下几
点赞 1
浏览 982
本文为 NGINX Sprint China 2022 年度线上大会的分享实录,点击这里免费观看大会完整视频回放。由于文章较长,将分为上下两篇发布。点击《分享实录 | 将NGINX打造成功能强大的API网关(上)》阅读上篇。 本次分享中,我们将讨论本次分享将全面介绍 API 网关的概念和功能,以及如何利用 NGINX 打造一个功能强大的 API 网关。
点赞 0
浏览 438