我正在设计DRF应用程序的授权。我需要使用角色,而不仅仅是权限。
我有一个模型(例如project
),其中我有一些可以被某些角色修改的信息(例如名称,描述)(例如admin
)。但同时还有其他角色(例如worker
)不能修改该模型中的信息,但仍然可以修改其他一些信息(例如初始和最终日期)。
我已经为这个问题考虑过两个解决方案。第一个是读取发送的HTTP请求,并根据请求的内容定义要采取的操作。这意味着每次将新字段添加到模型时,我都必须修改此逻辑。这听起来非常难以维护,容易出错并且可能会引入漏洞。
另一方面,我认为我可以将模型分成两个不同的模型。其中一个包含只有一个角色(admin
)可以修改的数据,另一个包含可以由两个角色(admin
,worker
修改的其他数据。这样,我就不必解析HTTP请求了,因为如果我收到影响第一个模型的POST / PUT请求而且用户有一个辅助角色,我可以直接拒绝它。
这种情况发生在多个模型中。
我想知道是否有默认的方式,或者我是否重新发明轮子。我认为这种情况必定非常普遍。例如,我可以想到一个git项目,其中一些用户可以访问项目中的一件事而不是其他人。
补充说明(非常感谢您的反馈):
我很可能会使用django-role-permissions模块来实现角色和权限。我不能使用django内置组,因为虽然你可以为它们添加权限,但我会使用它们对用户进行分组(与角色没有任何关系)。
我将在权限文件中创建角色和权限(基于字符串的权限,例如create_project
,modify_project_description
)之间的关系。
当收到每个请求时,我将检查哪些角色有权执行该操作,并检查用户是否是这些角色中的任何一个(基于活动的授权,这意味着在端点中我将检查活动/行动而不是角色。)
答案 0 :(得分:3)
听起来你想要一些字段级别的安全性。您可以考虑使用代理模型为受限用户提供对有限字段集的写访问权。
另一种选择可能是使用自定义序列化程序类,它将readonly应用于某些字段。 ViewSet子类上的get_serializer
可能是进行数据透视的好地方,您应该在self.request.user
中找到当前用户。
答案 1 :(得分:1)
经过深思熟虑后,我找到了两个解决方案。
第一个解决方案(而不是像我在问题中提到的那样划分模型)为每种必须发生的操作声明不同的端点(URL)。然后在每个端点serializer
中通过fields
类变量定义有效参数。
这意味着如果一个角色只能更新某些字段,我会为此操作创建一个ModelViewSet
,并且在与此ModelViewSet相关的serializer
类中只允许某些参数。
此解决方案存在许多问题,并且不完全RESTful。您最终可能会得到许多不同的网址。在我的情况下,鉴于API不大且行动有限,短期内可能不是问题,但确定当应用程序的要求发生变化时,这将是一个问题。
第二个(和选择的)解决方案是定义一个权限/角色表,您可以在其中定义操作必须发生的端点(如果您以正确的方式构建了应用程序)只是ModelViewSet
类名称),要执行的动作(列表,检索,创建......)可以交互的相关模型的字段以及可以与这些字段交互的角色。
我建议使用字典作为权限表的已使用数据结构,以便每个权限检查都是O(1)。
现在每次收到该端点的请求时,都应该使用该表进行权限检查。
我通过覆盖check_permissions()
类中的ModelSetView
方法来实现权限检查。请小心并保留原始的check_permissions()
功能。