若依权限系统分析(前后端分离版)

待我称王封你为后i 2023-10-12 15:50 149阅读 0赞

若依权限系统分析

  • 一:故事背景
  • 二:具体权限控制
    • 2.1 页面权限控制
    • 2.2 页面元素权限控制
  • 三:实现前端鉴权
    • 3.1 封装js与权限交互
      • 3.1.1 uni-app自带uni-request与权限交互
    • 3.2 vux状态管理
      • 3.2.1 自定义状态
      • 3.2.2 在vuex的store配置内添加我们新增的状态管理
    • 3.3 全局路由守卫鉴权
  • 四:总结提升

一:故事背景

最近在研究权限系统。秉承着站在巨人的肩膀上的原则,去学习了若依的权限项目。这里选用的是前后端分离版。去研究了界面的控制和页面内元素的控制。查看了其具体的实现方法,将其总结到这里。

二:具体权限控制

若依权限控制主要分为两大部分,第一部分是页面的控制,第二部分是页面上具体元素的控制。
在这里插入图片描述

  1. 在若依的系统中,菜单管理内可以看到所有元素。元素分为两种。一种是页面,另外一种是元素是页面内的具体元素。
  2. 无论是哪种元素,我们都可以自定义对应的 权限标识,通过权限表示来表示用户有没有具体的权限。

2.1 页面权限控制

页面权限控制是通过动态路由的方式进行的配置,我们从前端到后端,整个流程看一下其实现动态路由的整个过程

  1. src目录下的permission文件,这里代码意思是VueRouter中的全局前置守卫,用于在路由切换前执行一些逻辑操作。
    首先判断用户已经登录,有对应的token,然后去拉取用户的信息,拉去完之后去触发 Vuex的GenerateRoutes方法,去后端拉取具体的路由信息
    在这里插入图片描述
  2. 上文所述的 Vuex的GenerateRoutes方法 定义在 src.store.modules.permission.js 文件内,注意和上面的文件区分,二者目录不同
    在这里插入图片描述
    这部分代码,去后端查询了用户具有的路由权限等信息,将生成的可访问的路由配置作为 Promise 的结果返回。
    返回之后,第一部分的代码将可访问的路由动态的配置到了 Vue Router 中。
  3. 下面是请求路由数据返回的数据结构

    {

    1. "msg": "操作成功",
    2. "code": 200,
    3. "data": [
    4. {
    5. "name": "System",
    6. "path": "/system",
    7. "hidden": false,
    8. "redirect": "noRedirect",
    9. "component": "Layout",
    10. "alwaysShow": true,
    11. "meta": {
    12. "title": "系统管理",
    13. "icon": "system",
    14. "noCache": false,
    15. "link": null
    16. },
    17. "children": [
    18. {
    19. "name": "User",
    20. "path": "user",
    21. "hidden": false,
    22. "component": "system/user/index",
    23. "meta": {
    24. "title": "用户管理",
    25. "icon": "user",
    26. "noCache": false,
    27. "link": null
    28. }
    29. },
    30. {
    31. "name": "Role",
    32. "path": "role",
    33. "hidden": false,
    34. "component": "system/role/index",
    35. "meta": {
    36. "title": "角色管理",
    37. "icon": "peoples",
    38. "noCache": false,
    39. "link": null
    40. }
    41. },
    42. {
    43. "name": "Menu",
    44. "path": "menu",
    45. "hidden": false,
    46. "component": "system/menu/index",
    47. "meta": {
    48. "title": "菜单管理",
    49. "icon": "tree-table",
    50. "noCache": false,
    51. "link": null
    52. }
    53. },
    54. {
    55. "name": "Dept",
    56. "path": "dept",
    57. "hidden": false,
    58. "component": "system/dept/index",
    59. "meta": {
    60. "title": "部门管理",
    61. "icon": "tree",
    62. "noCache": false,
    63. "link": null
    64. }
    65. },
    66. {
    67. "name": "Post",
    68. "path": "post",
    69. "hidden": false,
    70. "component": "system/post/index",
    71. "meta": {
    72. "title": "岗位管理",
    73. "icon": "post",
    74. "noCache": false,
    75. "link": null
    76. }
    77. },
    78. {
    79. "name": "Dict",
    80. "path": "dict",
    81. "hidden": false,
    82. "component": "system/dict/index",
    83. "meta": {
    84. "title": "字典管理",
    85. "icon": "dict",
    86. "noCache": false,
    87. "link": null
    88. }
    89. }
    90. ]
    91. }
    92. ]

    }

2.2 页面元素权限控制

  1. 页面元素控制,通过权限id进行的相应控制,在若依的权限系统中,定义了v-hasPermi 和 v-hasRole 两个Vue指令。分别用来控制操作权限和角色权限处理。
    在这里插入图片描述
  2. 在用户登录的时候,会调用getInfo接口,获取用户对应的权限id的字段,并且将其存储到vuex的状态中,可以在其他的组件中通过Vuex的getters获取具体的信息
    在这里插入图片描述
    getUserInfo获得的具体的用户权限信息
    在这里插入图片描述
  3. 页面鉴权的时候直接通过 v-hasPermi 来进行对应的鉴权,如果该用户返回了对应的权限id,该用户对此控件就有具体的操作权限
    在这里插入图片描述

三:实现前端鉴权

基于若依,我自己封装了一个前端鉴权方式。通过调用若依权限接口,二次开发接口的方式,实现了路由鉴权
此实现主要涉及到以下几方面:
1.封装js与权限系统交互。
2.利用vuex实现状态管理,管理用户可访问的路由路径
3.全局路由守卫,实现鉴权

3.1 封装js与权限交互

我这里封装了两种js与权限系统交互,一种是利用axios、一种是利用uni-app框架的uni-request进行访问。

3.1.1 uni-app自带uni-request与权限交互

  1. //使用uni.request方式发送http请求
  2. //登陆获取token
  3. const AUTH_LOGIN_URL= "http://localhost:8000/auth/login"
  4. //获取用户权限
  5. const AUTH_USERINFO_URL="http://localhost:8000/auth/getResource"
  6. //返回token值等数据
  7. const state = {
  8. //token值
  9. token:'',
  10. //路由
  11. routes:[],
  12. //权限id
  13. permissions:[]
  14. }
  15. //登陆获取token,以及用户权限
  16. export function getAuth(data) {
  17. return new Promise((resolve, reject) => {
  18. sendRequest(AUTH_LOGIN_URL, 'post', data)
  19. .then(response => {
  20. // 请求token返回值
  21. console.log("response",response);
  22. state.token = response.data.token;
  23. console.log("token",data);
  24. getUserInfo(state.token).then(userRespone=>{
  25. state.permissions = userRespone.data.permissions;
  26. state.routes = userRespone.data.component;
  27. resolve(state)
  28. })
  29. })
  30. .catch(error => {
  31. // 请求发生错误,进行错误处理
  32. console.error(error);
  33. reject(error); // 将错误传递给调用者
  34. });
  35. });
  36. }
  37. //通过token获取用户权限
  38. function getUserInfo(token){
  39. return new Promise((resolve, reject) => {
  40. sendRequest(AUTH_USERINFO_URL, 'get', null,token)
  41. .then(response => {
  42. // 请求token返回值
  43. console.log("请求路由权限成功",response)
  44. resolve(response); // 将结果传递给调用者
  45. })
  46. .catch(error => {
  47. // 请求发生错误,进行错误处理
  48. console.error("发生错误",error);
  49. reject(error); // 将错误传递给调用者
  50. });
  51. });
  52. }
  53. function sendRequest(url, method, data, token) {
  54. return new Promise(function(resolve, reject){
  55. uni.request({
  56. url: url,
  57. method: method,
  58. data: data,
  59. header: {
  60. 'Authorization': 'Bearer ' + token // 设置 Authorization 头部
  61. }
  62. }).then(responses=>{
  63. // 异常
  64. if (responses[0]) {
  65. reject({
  66. message : "网络超时"});
  67. } else {
  68. resolve (responses[1]);
  69. }
  70. }).catch(error =>{
  71. reject(error);
  72. });
  73. })
  74. }

这个js专门与权限系统交互,查询用户的token,用户的权限等等。我这里主要定义了3个属性。token、routers、permissions,使用这三个实现对路由和页面元素的鉴权。当然我们还可以增加接口鉴权,等等

3.2 vux状态管理

上文所述查询到对应的权限之后,我们可以通过使用vuex将状态保存,利于我们项目之中进行使用。

3.2.1 自定义状态

通过自定义状态,定义应该交由vuex进行保存的状态

  1. import {
  2. getAuth } from "./uniCallAuth"
  3. const permission ={
  4. //各种状态
  5. state: {
  6. token:'',
  7. routes: [],
  8. permissions:[]
  9. },
  10. mutations:{
  11. //获得权限token
  12. AUTH_TOKEN: (state,token) =>{
  13. state.token = token
  14. },
  15. AUTH_PERMISSIONS: (state,permissions) =>{
  16. state.permissions = permissions
  17. },
  18. AUTH_ROUTERS: (state,routes) =>{
  19. state.routes = routes
  20. }
  21. },
  22. actions:{
  23. getUserAuth({
  24. commit},data){
  25. return new Promise(resolve => {
  26. getAuth(data).then(userData=>{
  27. console.log("userData",userData)
  28. //提交相关的状态
  29. commit('AUTH_TOKEN',userData.token);
  30. commit('AUTH_ROUTERS',userData.routes);
  31. commit('AUTH_PERMISSIONS',userData.permissions);
  32. console.log("用户状态已提交");
  33. resolve();
  34. })
  35. })
  36. }
  37. }
  38. }
  39. export default permission

3.2.2 在vuex的store配置内添加我们新增的状态管理

在这里插入图片描述
具体使用状态的方法;
在这里插入图片描述

3.3 全局路由守卫鉴权

在用户登陆时,通过调用权限进行鉴权,鉴权结束后,vuex就存储了相应的权限状态,我们通过定义方法,对全局路由进行鉴权

  1. Vue.prototype.$bus = new Vue();
  2. Vue.prototype.$bus.$on('uniNavigateTo', options => {
  3. // 全局路由守卫的具体逻辑
  4. console.log("全局路由守卫起作用",options);
  5. let newString
  6. //截取url防止get请求拼参
  7. if(options.url.includes('?')){
  8. newString = options.url.substring(0, options.url.indexOf('?'));
  9. }else{
  10. newString = options.url;
  11. }
  12. //登陆页面直接跳转
  13. if(newString == '/pages/views/user/phoneLogin' || newString =='/pages/views/seller/NotLogin'){
  14. console.log("普通页面直接跳转");
  15. uni.navigateTo(options);
  16. return;
  17. }
  18. console.log("newString",newString);
  19. //判断是否具有页面跳转权限
  20. if(! checkRouter(newString,store.state.permission.routes)){
  21. // uni.showToast(String("没有权限"));
  22. console.log("无法跳转uniNavigateTo",store.state.permission.routes);
  23. return;
  24. }
  25. console.log("应该跳转页面");
  26. uni.navigateTo(options);
  27. });
  28. Vue.prototype.$bus.$on('uniSwitchTab', options => {
  29. console.log("底部全局路由守卫起作用",options);
  30. //截取url防止get请求拼参
  31. let newString
  32. //截取url防止get请求拼参
  33. if(options.url.includes('?')){
  34. newString = options.url.substring(0, options.url.indexOf('?'));
  35. }else{
  36. newString = options.url;
  37. }
  38. //判断是否具有页面跳转权限
  39. if(! checkRouter(newString,store.state.permission.routes)){
  40. // uni.showToast(String("没有权限"));
  41. console.log("无法跳转uniSwitchTab");
  42. return;
  43. }
  44. console.log("应该跳转页面");
  45. uni.switchTab(options);
  46. });

四:总结提升

本文通过研究若依系统的权限,实现了自己项目的鉴权,并且在若依的基础上进行了对应的二次开发。理清了前端鉴权的方式,并且进行了实现。大家如果需要前端鉴权,可以参考。

发表评论

表情:
评论列表 (有 0 条评论,149人围观)

还没有评论,来说两句吧...

相关阅读