CAS 认证前后端分离 - 前端登录 鉴权 动态路由

/ vue / 没有评论 / 325浏览

上一篇概述了我在前后端分离认证的处理流程 CAS 认证之前后端分离 本文记录一下前后端分离之后, 前端登录流程, 权限校验, 动态路由等

登录流程简介

  1. iframe引入CAS登录页(CAS登录url从后端获取)
<iframe id="loginFrame" class="lxb-login-frame-from" :src="iframePath"></iframe>
  1. 通过特殊的与接口交互接口 /v1/creat-session 交由后端创建 sessionId 并通过 postMessage 传递回登录页
<iframe :src="http://xxxx/v1/creat-session" class="lxb-login-frame-creat-session"></iframe>
  1. 通过第2步拿到的sessionId建立socket连接

端接口无法确认前端用户, 此处用sessionId保持链接唯一性

window.addEventListener ('message', function (e) {
  // 获取从iframe子页面传递的sessionId
});

this.socket = io(constant.loginSocketIo + '?clientId=' + this.sessionId);
this.socket.on('connect', () => {
    this.log('connected ');
});

  1. 登录成功后,通过第3步建立的socket链接接收token

token存入 sessionStorage

改变Vuex中登录状态(状态被改变时, 同时加载系统动态路由部分, 用户信息等)

this.socket.on('messageevent', (data) => {
    // 登录成功
    sessionStorage.setItem('token', data.msgContent);
    this.$store.commit(LOGIN_STATE, true);
    this.$router.push('/home');
});
  1. 跳转页面至首页

  2. 在路由 beforeEach 中检查用户权限, 初次尝试加载权限, 用户菜单, 校验成功则进入next();

router.beforeEach((to, from, next) => {
    iView.LoadingBar.start();
    Util.title(to.meta.title);

    let userPermis = store.state.permis;
    let routerPermis = to.meta.permis;

    if (userPermis && routerPermis) {
        if (userPermis.includes(routerPermis)) {
            // 匹配到权限
            next();
        } else {
            // 没有权限
            next({replace: true, name: 'error-403'});
        }
    } else if (!userPermis && routerPermis && store.state.login) {
        // 用户没有权限, 路由需要权限, 尝试加载用户权限
        initMenus(() => {
            next({ ...to, replace: true });
        });
    } else {
        // 没有配置过权限
        next();
    }
});

/**
 * 加载菜单, 权限
 */
export function initMenus(callback) {
    Vue.prototype.get({
        url: '/lesp/v1/basic/data/menus',
        callback: (v) => {
            store.commit(USER_MENUS, v.menus);
            store.commit(USER_PERMIS, v.permis);
            if (callback) {
                callback();
            }
        }
    });
}

退出登录流程

  1. 创建iframe指向/logout, 先退出服务端

  2. iframe加载完成后, 清除 sessionStorge 中的token

  3. 跳转页面至登陆

this.logoutPath = constant.serverDomain + '/logout';
let iframe = document.getElementById("logoutFrame");
if (iframe.attachEvent) {
    iframe.attachEvent("onload", () => this.clearLoginToken());
} else {
    iframe.onload = () => this.clearLoginToken();
}

clearLoginToken() {
    this.$Modal.remove();
    sessionStorage.removeItem('token');
    this.$Message.info('退出成功 !');
    this.$router.push('/login');
}

权限控制及校验

路由权限控制

  1. 登录成功, 在 beforeEach 中检查用户权限, 并尝试加载用户权限, 用户菜单, 并重新执行此步骤

    • 用户信息 Vuex.state.user
    • 权限放入权限池 Vuex.state.permis
    • 用户菜单放入菜单池 Vuex.state.menus

按钮, 链接等权限控制

  1. 通过指令 v-auth:permis="权限标识" 控制
import store from '../store';
// 权限校验指令
export const haxAuth = {
    inserted (el, { value }, vnode) {
        // let permis = el.getAttribute('data-permis').trim();
        // 无权限, 则移除此dom
        if(value && !store.state.permis.includes(value)) {
            el.parentNode.removeChild(el);
        }
    },
    componentUpdated (el, { value }) {

    },
    unbind: function unbind (el, binding) {

    }
};

render中写法有所区别, 具体可自行查看文档, 此处只做demo

    directives: [
          {
              name: 'auth',
              value: permis,
              arg: 'permis'
          }
      ],

菜单权限

  1. 登录成功即加载用户菜单, 并放入菜单池

  2. 菜单组件中检测菜单池change, 并渲染页面

路由组装

  1. 登录成功即加载系统功能, 并组装路由数据放入Vuex.state.routers

  2. watch Vuex.state.routers, 并填入路由中

    this.$router.addRoutes();

至此完成了CAS认证登录, 对菜单, 按钮, 链接, 展示文本等做了鉴权, 并实现了动态路由, 由权限控制路由.