关于 vue项目中的 用户权限 控制 (含奇葩需求)

4,072 阅读3分钟

项目背景:

还是前几篇文章中所涉及到项目,现在 才 做权限控制 不过还好,现在这个项目的业务还不复杂,还来得及,只能这样安慰自己

如下图所示:

  1. 在login 成功以后, 后端返回 一些用户账号的基本信息 、功能权限身份权限
  2. 这样本身并没有什么问题,前端取到数据后,把数据存起来然后全局展示和限制就行了
  3. 现在问题来了,客户提了一个让我和后段都傻眼的需求

客户: 我不想从你们登录页面进,我想从我们其他系统跳进你这个系统,方便我们操作人员直接进来填数据,新增项目等等

老板: 行,没毛病!

后端:老板,我不想学后端了,呜呜~~

我:后端大哥,你行的,俺相信你,正道的光,照在了大地上~


5.png

综合分析:

  • 小公司,没办法,客户就这样,想体验类似sso的感觉,但是呢又不愿给那个钱,李姐
  • 然后,没办法,开会呗,整个什么方案才好呢?
  • 最终一致通过,后端直接来跳我的页面,我把地址什么的都给后段,
  • 客户不是说要填数据么?行,后端直接把参数从URL地址栏传过来,我取出来展示
  • 诶,等会儿,是不是忘了一件重要的事,后端生成一个URL来进我的页面没问题
  • 但是,我怎么取上面图中的那些数据呢?上面那个是login接口返回的,
  • 你用户根本就不跳我的login页面啊,那不是进来了什么都没有啊,而且权限和身份我咋控制呢?
  • 得,这后端开始装起来了 我给你新的接口,你判断下是不是从login进来的呗,不是你就请求我这个,返回值跟login一样
  • 大哥,牛掰,行。

具体方案:

  1. 关于 前端如何做权限控制之类的文章网上一大堆,多看看就行了,这里就不详细展示了 前端权限控制 基本跟这个大哥思路差不多
  2. 但是 他们基本都用的vuex, 我不怎么喜欢用它,还是太懒了,不想学语法
  3. 所以,我存用户的信息,我就用了一个全局的$bus来存,还是比vuex方便一点,个人觉得,不喜勿喷

后端会生成一个类似这样的链接给用户,让用户直接进入 http://your ip :your port/api/lifecyle?account=182xxxx5981&role=in_role&op=new-prj&oppid=12345&prjname=xx天网&city=xx&county=xxxx&cons-1-com=公司名&cons-1-person=grj&cons-1-phone=181111111111&cons-2-com=xxx&cons-2-person=lll&cons-2-phone=1392222222&sel-cons-com=A&sel-cons-person=aa&sel-cons-phone=139111111111&sign=8c99c4ce9fcfde232c330450bea0e88d

打开的效果预览:

6.png

必要说明:

朋友们也许会想知道是怎么实现的,这里简单说下

  1. 由于登录用的是cookie,所以在生成链接的时候,后端就已经记录下了登录的cookie,所以这样是可以登录的
  2. 取数据就不说了,之前的文章也写过URL取参数的文章
  3. 要判断 后端传过来的 有参数才填写, 没有参数就不填写
  4. 以上三点都比较 基础(chunshufeihua) 其实最麻烦的还是后面这个问题

你这样是能登录进来了,但是会和 自己login的时候相互影响, 举个例子:

假如自己login的时候是 admin1的账号信息, 但是 那边跳链接进来的是 admin2 的账号 那么此时 按照正常的逻辑,应该是 需要一个if 来判断是否是从login进入的 如果是,就展示login的 admin1 如果不是, 就应该请求一下 后端新提供的 update_user_info 接口 来展示admin2 的信息

现在核心的问题是————到底应该在什么时候或者在哪里写这个if才合理?

值得注意的一个问题是:这个 update_user_info 必定是写在全局的的一个请求,不然就整复杂了

最开始的思路: 直接在App.vue 里面请求,记录用户信息, 然后provide,inject 全局使用 但是这样会有一个 异步问题, 发出去的请求还没回来,就已经需要用到这个数据来展示页面了 所以,这样做肯定不科学,也不对。。。

直到我看到了下面这个东西,给了我启发:

7.png

得益于 尤雨溪buff加成,我决定采用 第二种方案 导航完成之前获取

代码:

main.js 中: 定义一个全局bus 来存 用户信息

import Vue from "vue";
window.$bus = new Vue({
  data() {
    return {
      account:{
        init: false,
        data: null
      }
    };
  },
});

Vue.prototype.$bus = window.$bus;

router.js 中:

import Vue from "vue";
import VueRouter from "vue-router";
import Axios from "axios";
Vue.use(VueRouter);

直接用 这个 路由全局前置守卫 完美解决我的顾虑 尤大yyds
router.beforeEach((to, from, next) => {
  // console.log('refresh!');
  // console.log(to);
  if (to.name != "login") {
  	写这个if 的目的是 避免 每进一个页面都请求的情况 变相节流吧 hhh
    if (!window.$bus.account.init) {
      Axios({
        url: "/api/user/update_user_info",
        method: "POST",
        responseType: "json",
      })
        .then((data) => {
          // console.log("update", data);
          window.$bus.account.init = true;
          window.$bus.account.data = data.data;
          此时的 这个数据可以全局通用,还是比较方便的,
          next();
        })
    }else{
      next();
    }
  }else{
    next();
  }
});

结语:

  1. 自己最开始存用户信息,用的是 浏览器存储,主要是不想一刷新,用户啥信息都没有了,想着应该没啥大问题,但是遇到这种业务肯定要有所改变,还有 存那么重要的数据在浏览器也不安全,反正以后也长记性了
  2. 还是应该多看看文档,不要怀疑尤的能力
  3. 用户体验还是很重要的,以后做东西应该会多考虑下交互和功能的延展