后台管理权限控制(后端 DRF 框架 + 前端 Vue 框架)

DRF 权限控制

  • 前提:用户表中有用户类型这一字段
定义权限控制类
  • 定义 Admin 用户和 VIP 用户的权限控制类
    from rest_framework import exceptions
    from app01 import models
    from rest_framework.permissions import BasePermission
    class AdminUserpermission(Basepermission):
            #使放回的错误信息变成你想显示的信息
            massage = '您没有权限!'
            #注意这里的方法名固定
            def has_permission(self, request, view):
            user_type = request.user.user_type
            if user_type == 2:
                    #返回True表示验证通过
                return True
            else:
                    #返回False表示验证不通过
                return False
    
    class VIPUserpermission(Basepermission):
            #使放回的错误信息变成你想显示的信息
            massage = '您没有权限!'
            #注意这里的方法名固定
            def has_permission(self, request, view):
            user_type = request.user.user_type
            if user_type == 1:
                    #返回True表示验证通过
                return True
            else:
                    #返回False表示验证不通过
                return False
    复制代码
使用权限控制类
  • 在视图中使用定义好的权限控制类
全局使用
  • 在 setting 中配置
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': ['VIPUserPermission']
    }
    复制代码
    • 一般全局使用的是权限级别最低的那个,局部如果需要更高级别的权限则可以重写权限
  • 访问 Books 视图
    class Books(APIView):
    # 因为在全局配置了 VIP 权限,所以需要 VIP 用户权限
    def get(self, request):
        books = models.Book.objects.all()
        books_res = BooksDRF(books, many=True)
        authors = models.Author.objects.all()
        authors_res = AuthorsDRF(instance=authors,many=True)
        response = {'status':200,'msg':'查询成功!','books':books_res.data,'authors':authors_res.data}
        return JsonResponse(response, safe=False)
    复制代码
局部使用
  • 局部可以使用自己的权限,覆盖全局权限
    class UserInfo(APIView):
    # 局部重写权限,需要 AdminUserpermission 管理员权限
    permission_classes = [AdminUserpermission, ]
    def get(self, request):
        userInfos = models.User.objects.all()
        userInfos_res = UserInfoDRF(books, many=True)
        response = {'status':200,'msg':'查询成功!','userInfos':userInfos_res.data}
        return JsonResponse(response, safe=False)
    复制代码

Vue 后台管理权限控制

  • 用户类型:超级管理员:admin,普通编辑用户:editor
实现步骤
  1. 创建 vue 实例的时候将 vue-router 挂载,但这个时候 vue-router 挂载一些登录或者不用权限的公用的页面
  2. 在路由表(router.js)中通过 meta 标签来标示改路由(页面)能访问的权限有哪些,如:meta: { role: ['admin','editor'] } 表示该页面只有 admin 和 editor 才可以访问
  • 配置路由访问权限
    // router.js
    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    export const constantRouterMap = [
      {
        path: '/',
        redirect: '/login',
        hidden: true
      },
      {
        path: '/login',
        name: '登录页面',
        hidden: true,
        component: resolve => require(['../views/login/Login.vue'], resolve)
      },
      {
        path: '/Readme',
        // name: 'Readmehome',
        index: 'Readme',
        meta: {
          title: 'Readme',
          icon: 'el-icon-menu'
        },
        component: resolve => require(['../components/common/Home.vue'], resolve),
        children: [
          {
            name: 'Readme',
            path: '/',
            meta: { title: 'Readme', icon: 'el-icon-menu' },
            component: resolve => require(['../components/page/Readme.vue'], resolve)
          }
        ]
      }
    ]
    
    export default new Router({
      routes: constantRouterMap
    })
    // 异步挂载的路由
    // 动态需要根据权限加载的路由表
    export const asyncRouterMap = [
      {
        path: '/permission',
        // name: 'permissionhome',
        meta: {
          title: 'permission',
          icon: 'el-icon-setting',
          roles: ['admin']
        },
        component: resolve => require(['../components/common/Home.vue'], resolve),
        children: [
          {
            name: 'permission',
            path: '/permission',
            meta: {
              title: 'permission', icon: 'el-icon-menu', roles: ['admin']
            },
            component: resolve => require(['../components/page/permission.vue'], resolve)
          }
        ]
      },
      { path: '*', redirect: '/404', hidden: true }
    ]
    复制代码
  • 特别说明
    • 这里有一个需要非常注意的地方就是 404 页面一定要最后加载,如果放在 constantRouterMap 一同声明了404,后面的所有的页面都会被拦截到 404
  1. 当用户登录后获取用 role
  2. 将 role 和路由表每个页面的需要的权限作比较,调用 router.addRoutes(store.getters.addRouters) 添加用户可访问的路由,生成最终用户可访问的路由表,并将路由表存在 vuex 里面
  • permission.js
    // permission.js
    import router from './router'
    import store from './store'
    import { Message } from 'element-ui'
    import { getToken } from '@/utils/auth' // 验权
    
    const whiteList = ['/login', '/authredirect'] // 不重定向白名单
    
    router.beforeEach((to, from, next) => {
      if (getToken()) { // 判断是否有token
        if (to.path === '/login') {
          next({ path: '/' })
        } else {
          if (store.getters.roles.length === 0) {
            console.log('roles====0')
            store.dispatch('GetInfo').then(res => { // 拉取用户信息
              const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
              console.log('roles?', roles)
              store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
                console.log('addrouters', store.getters.addRouters)
                router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
                next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
              })
            }).catch(() => {
              store.dispatch('FedLogOut').then(() => {
                Message.error('验证失败,请重新登录')
                next({ path: '/login' })
              })
            })
          } else {
            console.log('====1')
            next() // 当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          next('/login')
        }
      }
    })
    复制代码
  1. 根据 vuex 中可访问的路由渲染侧边栏组件:<v-sidebar :routers="routers"></v-sidebar>
  • 在需要的页面使用导航栏
    <template>
        <div class="wrapper">
            <v-head></v-head>
            <!-- 循环输出 vuex 里面存的路由信息 -->
            <v-sidebar :routes="routes"x</v-sidebar>
            <div class="content">
                 <transition name="move" mode="out-in"><router-view></router-view</transition>
            </div>
        </div>
    </template>
    复制代码
  1. 创建左侧导航栏组件 Sidebar
  • 使用 ElementUI 的左侧导航栏组件和 Vuex 中的动态生成的 routers 数据,动态的创建出导航栏页面

参考和感谢

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享