我有一个简单的root资源工厂:
class Root:
__acl__ = [
(Allow, Authenticated, 'edit')
]
现在对于一些“特殊”路线,我需要创建另一个资源工厂
config.add_route('special', '/special/test', factory=SpecialFactory)
class SpecialFactory:
__acl__ = [
(Allow, Authenticated, 'special_edit')
]
现在,我想让Root
成为SpecialFactory
的父母 - 我应该怎么做?
这是正确的方式......
class SpecialFactory:
def __init__(self, request):
self.request = request
self.__parent__ = Root(request)
self.__name__ = 'special'
__acl__ = [
(Allow, Authenticated, 'special_edit')
]
我也完全不了解__name__
的目的以及它应该设置的内容。
此外,Pyramid何时会遍历__parent__
链,何时不会?对于像这样的视图配置:
@view_config(route_name='special', permission='special_edit')
def something(req):
pass
金字塔会“收集”两个权限(special_edit
和edit
)还是仅一个(special_edit
)?
请详细说明计算权限的“流程”。
答案 0 :(得分:12)
__name__
仅在通过遍历生成网址时才会考虑,因此请不要担心。
首先,工厂参数是工厂。意思是,它的某些对象"接受request
对象,并期望收回一个实际上是树根的对象。
class Root:
def __init__(self, request):
self.request = request
def resource_factory(request):
return Root(request)
add_route(..., factory=resource_factory)
请注意,工厂在这里是显而易见的。常用的快捷方式是使用构造对象实例实际返回自身的事实。因此Root(request)
从外部看起来完全相同,并返回与resource_factory(request)
相同的对象。
很好,所以现在我们有一个" root"我们可以从中开始遍历的对象。当然,这并不一定是树的实际根,它只是遍历的起点。
您尚未向traverse
添加add_route
参数,因此遍历不会去任何地方,它只会将根对象作为上下文返回。查找上下文对象是遍历练习的整个目标。
所以,现在我们有了一个背景。耶。
金字塔的授权通过结合"有效的原则和#34;用户,使用" context"和#34;许可"。这三件事是您的授权策略将用于确定是允许还是拒绝操作的内容。"有效的校长"来自身份验证策略,代表请求后面的用户。
" context"和#34;许可"是你想要的。在大多数情况下,它们是request.context
和视图的权限,但pyramid.security.has_permission()
可以接受任何上下文对象和任何权限,并返回允许或拒绝结果。
因此,我们已获得授权所需的3项内容。现在,如何授权?那取决于授权政策。默认情况下为ACLAuthorizationPolicy
。那它是如何运作的?
ACLAuthorizationPolicy
从context
开始,然后向前走过"沿袭"那个对象。 "血统"被定义为通过将每个对象的__parent__
追溯到最后创建的列表,其中不再需要__parent__
。因此,在您的示例中,上下文将是SpecialFactory
的实例,以及" lineage"上下文是列表[ SpecialFactory(request), Root(request) ]
。
ACL匹配的工作方式(在ACLAuthorizationPolicy
中)是它遍历从上下文回到根的沿袭中的每个对象,按顺序搜索每个对象__acl__
。它找到的第一场比赛是胜利者。 ACL中的条目由"(Allow
或Deny
,principal
,permission
)"定义。和match是ACL中包含我们正在寻找的相同权限的条目,因为主体匹配当前用户的有效主体列表中的一个主体。找到匹配后,搜索停止并返回结果。
如果此算法不适合您,请替换授权策略。它是高度可插拔的,默认实现很容易理解(总共只有几行代码)。您甚至可以制定自己的政策,根本不关心上下文,此时您可以忽略所有这些遍历的废话。它取决于你。