前后端分离鉴权

前后端分离 通用鉴权方案 (分组权限)

前言

做了几个前后端分离的项目,都遇到了权限管理的问题。这里总结一下实现的方案及注意事项。

问题

鉴权的需求一般是这样的,假设有 A(主页), B, C, D(系统配置页) 四个页面:

超级管理员能访问所有页面。
一类管理人员访问AB页面
二类管理人员访问AC页面
测试人员访问能访问某几个指定页面 AB
普通用户只能访问A
用户与页面是多对多的关系,相互之间会有交叉,所以使用简单的分级权限实现起来是很麻烦的。如果新增一个用户,使其能访问ABC,就需要新建一个分级,使其只有ABC的权限。假设某一天又有用户需要访问 ACD呢?

因此,在权限有交叉的情况下,使用分组权限是比较好的方案。

分组权限

分组权限的核心思想可以用下图表示

前后端分离鉴权_第1张图片

用户与分组, 分组与权限都是多对多关系
鉴权针对分组
这么说有点抽象,我们还是结合之前的例子,看用分组权限怎么解决。

系统建立 超级管理员、一类管理员、二类管理员、测试员、普通用户 几个分组。
用户和分组之间 通过 用户-分组 表建立多对多关系
页面设置 针对用户的分组进行鉴权,通过则允许访问

Talk is cheap, show me the code

下面用派森的demo解释一下

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

你可能感兴趣的:(python)