Django 按组控制权限类及定义方法详解
作者:alue
任务描述
后端接口,能够方便的使用角色组权限控制, 例如
# 基于函数的控制 @api_view(['GET']) @permission_groups(['开发组','测试组']) def api(request): return Response() # 或者在类中 class SomeViewSet(): group_names = ['开发组','测试组']
只要增加一行代码, 声明组名称, 就能够让这个接口只对该角色开放权限.
方法
思路很简单, 就是仿照 DRF 的权限控制, 自定义自己的权限验证行为即可.
权限类定义
仿照drf的权限类 IsAuthenticated 的写法:
class IsAuthenticated(BasePermission): def has_permission(self, request, view): return bool(request.user and request.user.is_authenticated)
我们的权限类,需要一个组名称的参数, 所以需要用工厂模式, 根据参数, 动态生成类.
def sigma_permission(): class SigmaPermission(BasePermission): def __init__(self, group_names: List[GroupName] = None): self._sigma_groups = group_names def has_permission(self, request, view): if request.user.is_anonymous: return False return set(request.user.groups.all().values_list('name', flat=True)) & set(self._sigma_groups) return SigmaPermission # 能够接受参数的权限类 SigmaPermissionFactory = sigma_permission()
我们用类似闭包的形式, 构建了自己的权限类 SigmaPermission
, 并且能够接收组名称列表作为参数, 内部方法 has_permission
实现了权限验证的工作.
下面, 就要要看看权限类该怎么使用. 根据两种场景, 分别采用装饰器和基类继承的方式.
基于函数的权限控制
可以参考drf的 permission_classes
装饰器的写法
def permission_classes(permission_classes): def decorator(func): func.permission_classes = permission_classes return func return decorator
我们定义自己的组权限装饰器:
def permission_groups(group_names: List[GroupName]): """ 组权限装饰器 """ def decorator(func): groups_permission = SigmaPermissionFactory(group_names) if hasattr(func, 'permission_classes') and func.permission_classes is not None: func.permission_classes = [*func.permission_classes, lambda: groups_permission] else: func.permission_classes = [lambda: groups_permission] return func return decorator
注意: 这里注册 permission_classes
时, 必须要用 lambda 函数的方式. 这是因为, 我们的类工厂生成 groups_permission 时, 已经完成了初始化. 而Python的类只有在初始化时是 callable 的, 一旦初始化完成之后, 就不能再次callable. 而 permission_classes
里的元素必须可以 callable , 所以用 lambda 函数的方式实现.
基于类的权限控制
这个方法就简单许多, 只用重载 get_permissions
方法就行.
class SigmaViewSet(ModelViewSet):
def get_permissions(self): permissions = [permission() for permission in self.permission_classes] if hasattr(self, 'group_names '): groups_permission = SigmaPermissionFactory(self.group_names ) permissions.append(groups_permission) return permissions
总结
通过这个案例, 我们能够学到工厂函数/类的callable/lambda 函数的使用场景.
以上就是Django 按组控制权限类及定义方法详解的详细内容,更多关于Django 按组控制权限的资料请关注脚本之家其它相关文章!