做了几个前后端分离的项目,都遇到了权限管理的问题。这里总结一下实现的方案及注意事项。
鉴权的需求一般是这样的,假设有 A(主页), B, C, D(系统配置页) 四个页面:
超级管理员能访问所有页面。
一类管理人员访问AB页面
二类管理人员访问AC页面
测试人员访问能访问某几个指定页面 AB
普通用户只能访问A
用户与页面是多对多的关系,相互之间会有交叉,所以使用简单的分级权限实现起来是很麻烦的。如果新增一个用户,使其能访问ABC,就需要新建一个分级,使其只有ABC的权限。假设某一天又有用户需要访问 ACD呢?
因此,在权限有交叉的情况下,使用分组权限是比较好的方案。
分组权限的核心思想可以用下图表示
用户与分组, 分组与权限都是多对多关系
鉴权针对分组
这么说有点抽象,我们还是结合之前的例子,看用分组权限怎么解决。
系统建立 超级管理员、一类管理员、二类管理员、测试员、普通用户 几个分组。
用户和分组之间 通过 用户-分组 表建立多对多关系
页面设置 针对用户的分组进行鉴权,通过则允许访问
from typing import List
# 分组表
groups = {
1: '超级管理员',
2: '一类管理员',
3: '二类管理员',
4: '测试员',
5: '用户'
}
# 用户表
users = {
1: '用户A',
2: '用户B',
3: '用户C'
}
# 用户分组表
user_group = {
1: [1], # 用户A -> 超级管理员
2: [2], # B -> 一类管理员
3: [3, 4] # C -> 一类管理员、测试员
}
# 页面及允许的用户组
pages = [
{
'name': '首页',
'allow': None # 表示所有用户均可看到
},
{
'name': '页面1',
'allow': ['超级管理员', '一类管理员', '测试员']
},
{
'name': '页面2',
'allow': ['超级管理员', '二类管理员', '测试员']
},
{
'name': '设置页',
'allow': ['超级管理员']
}
]
def get_group_names_by_uid (uid: int) -> List[str]:
"""
通过uid获取权限组列表
"""
res = []
for gid in user_group[uid]: # 取出用户对应的权限组列表并转换为组名列表
res.append(groups[gid])
return res
def auth (user_access: List[str], page_auth: List[str]) -> bool:
"""
两个集合是否有交集,有则通过
"""
if not page_auth: # 页面不鉴权
return True
for g in user_access:
for a in page_auth: # 因为元素很少,所以直接暴力双循环也很快
if g == a:
return True
return False
if __name__ == "__main__":
for uid, name in users.items(): # 用户尝试访问所有页面
for page in pages:
access = get_group_names_by_uid(uid) # 查出用户的权限组
print(name, ' 访问:', page['name'], '通过' if auth(access, page['allow']) else '未通过')
print('\n')
————————————————
原文链接:https://blog.csdn.net/liaodong2010/article/details/101057847