zoukankan      html  css  js  c++  java
  • 权限理解及vue实现

    权限控制归根到底是用来控制对资源的访问,它需要前后端共同来实现。

    一、后端实现

    从后端来说,权限控制的对象一般是接口,有时候会细致到某个具体的方方法,核心就是保护对底层数据库的访问。

    1.模型设计

    一般涉及如下几张表,包括user表、role表(也可以理解为拥有一系列权限的group)和permission表,

    user_role和role_permission一般是为了实现用户和组,以及组和权限的多对多灵活控制的辅助表,

    就我个人理解,如果更核心一些,其中只需要两张表:user表和permission表,role表的出现更多的是因为权限粒度很小的时候,一个用户会对应很多权限,一个一个的开非常繁琐,对一系列权限进行归纳整合成一个角色,更方便管理。

    CREATE TABLE `user` (
    `id` bigint(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(255) NOT NULL,
    `password` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
    );
    CREATE TABLE `role` (
    `id` bigint(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
    );
    CREATE TABLE `user_role` (
    `user_id` bigint(11) NOT NULL,
    `role_id` bigint(11) NOT NULL
    );
    CREATE TABLE `role_permission` (
    `role_id` bigint(11) NOT NULL,
    `permission_id` bigint(11) NOT NULL
    );
    CREATE TABLE `permission` (
    `id` bigint(11) NOT NULL AUTO_INCREMENT,
    `url` varchar(255) NOT NULL,
    `name` varchar(255) NOT NULL,
    `description` varchar(255) NULL,
    `pid` bigint(11) NOT NULL,
    PRIMARY KEY (`id`)
    );

    有了这些表之后,在后端就可以设计全局的拦截器,对权限和路由进行判断,没有权限的访问会被直接拒绝或者跳转。

    2.方法保护

    spring security还有一些更细节的控制,会采用注解的方式加在service层的方法上,避免有人突破了URL层的限制。显然这样可以更好的保护对数据层的访问。

    import org.springframework.security.access.annotation.Secured;
    import org.springframework.security.access.prepost.PreAuthorize;
    class A{
    @Override
        @Transactional
        @Secured("ROLE_ADMIN")
        public void createModel(String tbName, List<Columns> columnsList) {
            saveModelColumns(columnsList);
            createDataTable(tbName);
        }
    
        @PreAuthorize("hasRole('ADMIN') and hasRole('DBA')")
        public void saveModelColumns(List<Columns> columnsList) {
            columnsDao.batchInsertColumns(columnsList);
        }
    
    }

    二、前端实现

    前端的权限控制五花八门,在我看来,大概是通过如下三个方面来实现的。

    1.通过路由跳转时的拦截控制用户对具体页面的访问

    router.beforeEach((to, from, next) => {
      const auth = store.state.user.authority;
      const token = store.state.user.token;
      /*1.去登录页没有权限要求;
        2.去登录页之外的页面要判断是否登录,未登录先跳转到登录页;
        3.如果已登录则判断是否有权限,没权限则返回403;
        4.权限验证通过,直接放行
        */
      if (to.name === "Login") {
        next();
      } else if (!token || token === "") {
        next({ name: "Login" });
      } else if (to.meta.authority && !auth.includes(to.meta.authority)) {
        next({ name: "Forbidden" });
      } else {
        next();
      }
    });

    2.通过对按钮的显示隐藏控制用户对具体内容的编辑

    这个主要通过自定义指令实现

    user.js用户权限缓存

    const state = () => ({
      username: "",
      token: "123",
      authority:['add','edit','delete','chart_view'],
    });

    main.js

    app.directive('auth', {
        mounted(el, binding) {
            if (!store.state.user.authority.some(item=> item===binding.value)) {
                el.parentNode && el.parentNode.removeChild(el)
            }
        }
    });

     *.vue

      <el-button v-auth="'add'"  size="mini" type="primary" plain  @click="handleCreate">添加</el-button>

    只有拥有add权限的用户才能看见这个添加按钮

    3.通过菜单项的显示隐藏控制用户对具体页面的访问

    这个主要用于提升用户体验,如果用户没有权限也能看到某个菜单,一点就是403,体验会很差,还不如不让看见。

    在通过route.js菜单渲染的时候,加入权限的过滤,就可以实现不同用户看到不同的菜单栏

    methods: {
        //渲染菜单时根据当前用户的权限排除当前用户没有权限的菜单
        getLinks() {
          let rt = this.$router.options.routes;
          rt.forEach((item) => {
            if (item.path === "/doc") {
              this.linkData = [];
              item.children.forEach((child) => {
                if (child.name) {
                  const auth = this.$store.state.user.authority;
                  if (child.meta) {
                    if (auth.includes(child.meta.authority)) {
                      this.linkData.push(child);
                    }
                  } else {
                    this.linkData.push(child);
                  }
                }
              });
              
            }
          });
        },
      },

    当系统要求对权限做特别细粒度的控制时,可以采用用户-权限这种模式,如果要求不是那么高,推荐使用用户-角色这种比较粗粒度的实现。

  • 相关阅读:
    java基础---多线程---volatile详解
    java基础---多线程---线程的几种状态及其转换,wait,notify,sleep,yield,join
    java基础---设计一个死锁
    count(1) and count(*),count(字段)区别及效率比较
    mysql之字段约束-第五篇
    mysql之数据表基本操作-第四篇
    mysql之数据类型-第三篇
    mysql之存储引擎-第二篇
    mysql之数据库操作-第一篇
    Redis详解
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15736030.html
Copyright © 2011-2022 走看看