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
实现步骤
- 创建 vue 实例的时候将 vue-router 挂载,但这个时候 vue-router 挂载一些登录或者不用权限的公用的页面
- 在路由表(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
- 当用户登录后获取用 role
- 将 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') } } }) 复制代码
- 根据 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> 复制代码
- 创建左侧导航栏组件 Sidebar
- 使用 ElementUI 的左侧导航栏组件和 Vuex 中的动态生成的 routers 数据,动态的创建出导航栏页面
参考和感谢
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END