wangxingkang / website

阿康的个人站
https://xingkang.wang
3 stars 0 forks source link

简单聊聊中后台权限控制的实现 #1

Open wangxingkang opened 4 years ago

wangxingkang commented 4 years ago

WechatIMG94

前言

权限控制在中后台项目非常常见,项目根据实际情况以及产品要求在权限粒度、实现方式方面有很多不同方式,下面将结合我的工作经历对此展开详细阐述。

权限粒度

一般的权限分为前端权限和后端权限,后端权限可理解为接口权限,前端前端一般为页面权限操作权限,权限粒度的控制一般有两种,也就是页面权限操作权限

页面权限

访问每个页面的权限

操作权限

常理解为按钮权限 一般控制到操作权限会包含页面权限的控制

实现方式

一般而言,控制权限都是通过一个唯一Code去做权限控制,既要控制前端权限,又要控制后端权限,总结而言,可归纳为两种方式

1. 用前端权限去关联后端权限

维护一套前端权限,并将后端权限与之关联,只需要分配给用户前端权限,达到前后端控制权限的目标

优点:

缺点:

2. 前后端共用一套约定去实现权限管理

优点:

缺点:

解决方案

针对上面两种各出一个解决方案

方案1

维护一套前端权限体系,并跟后端权限做关联,并为每个权限指定唯一Code,用户登录后 获取 权限集合,根据是否存在 某个Code 进行权限控制

Code 可遵从以下规则

方案2

共同遵从一套约定,前端可以直接使用后端的API权限去实现权限控制,前段时间研究阿里云的权限控制,感觉是非常好的一个方案,通过一套语法规则去描述权限,有很好的的扩展性,下面简单介绍下语法(做了简单修改),详细请查看 Policy 语法结构

Policy 语法

policy  = {
     <version_block>,
     <statement_block>
}
<version_block> = "version" : ("1")
<statement_block> = "statement" : [ <statement>, <statement>, ... ]
<statement> = { 
    <effect_block>,
    <action_block>
}
<effect_block> = "effect" : ("allow" | "deny")  
<action_block> = "action" : ("*" | [<action_string>, <action_string>, ...])

Policy 语法说明:

Policy 样例

{
    "version": "1",
    "statement": [
        {
            "effect": "allow",
            "action": "user/list"
        },
        {
            "effect": "allow",
            "action": [
                "user/create",
                "user/update"
            ]
        }
    ]
}

库封装

已经封装了对应的工具库,可以对policy语法进行解析,并提供验证权限功能,具体请查看policy

React技术栈实践

维护了一个react-admin-template项目,对上面的方案进行了相关实践,已运用到公司项目中,反馈良好;

  1. 封装权限组件

主要代码:authorized.tsx

  1. 操作权限控制
const Example = props => {
  const { policy } = props;

  if (policy.multipleVerify('module/action')) {
     return (
       <div>Hello Policy</div>
     )
  } else {
     return (
        <div>Not Auth</div>
     )
  }
}

export default connect(({ user }) => ({
  policy: user.policy
}))(Example);
  1. 页面权限控制

后端是否可以不使用policy语法?

完全可以,历史项目使用的话可以由前端模拟,具体做法如下

const policy = new Policy([])

 policy.addPolicy({
     version: 1,
     statement: [
         {
            effect: 'allow',
            action: allowActions
          }
     ]
});

只需将权限处理为 module/action的形式即可

FatDoge commented 4 years ago

最近刚好有个需求需要做鉴权,目前方案是后端维护一份权限点文档,权限点粒度可以到路由级别,也可以到接口级别,接口级别的一般映射到具体元素。每个用户登陆后可以通过currentUser接口里的authority字段获取一个权限点数组(e.g:[1,2,3,4,5,6]),配合antdpro的路由鉴权玩还行。

wangxingkang commented 4 years ago

可以具体点吗? 你的使用上面的方式其实也是可行的,公用一个module就可以, 有好的想法欢迎讨论; 现在已提供 权限组件 https://antd-plus.alitajs.com/components/data-display/authorized