您可以通过使用为此目的设计的自定义资源树将ACLAuthorizationPolicy 与 URL Dispatch 结合使用来执行此操作。
例如,您拥有Foo 对象的权限和Bar 对象的权限。这些 ACL 可以通过使用 url 遍历资源树来找到:
/foos/{obj}
/bars/{obj}
然后,您的资源树将成为权限层次结构,您可以在树中的任何位置将__acl__ 放置在资源对象上:
root (Root)
|- foos (FooContainer)
| `- {obj} (Foo)
`- bars (BarContainer)
`- {obj} (Bar)
您可以在资源树中表示此层次结构:
class Root(dict):
# this is the root factory, you can set an __acl__ here for all resources
__acl__ = [
(Allow, 'admin', ALL_PERMISSIONS),
]
def __init__(self, request):
self.request = request
self['foos'] = FooContainer(self, 'foos')
self['bars'] = BarContainer(self, 'bars')
class FooContainer(object):
# set ACL here for *all* objects of type Foo
__acl__ = [
]
def __init__(self, parent, name):
self.__parent__ = parent
self.__name__ = name
def __getitem__(self, key):
# get a database connection
s = DBSession()
obj = s.query(Foo).filter_by(id=key).scalar()
if obj is None:
raise KeyError
obj.__parent__ = self
obj.__name__ = key
return obj
class Foo(object):
# this __acl__ is computed dynamically based on the specific object
@property
def __acl__(self):
acls = [(Allow, 'u:%d' % o.id, 'view') for o in self.owners]
return acls
owners = relation('FooOwner')
class Bar(object):
# allow any authenticated user to view Bar objects
__acl__ = [
(Allow, Authenticated, 'view')
]
通过这样的设置,您可以将路由模式映射到您的资源树:
config = Configurator()
config.add_route('item_options', '/item/{item}/some_options',
# tell pyramid where in the resource tree to go for this url
traverse='/foos/{item}')
您还需要将路线映射到特定视图:
config.add_view(route_name='item_options', view='.views.options_view',
permission='view', renderer='item_options.mako')
太好了,现在我们可以定义我们的视图并使用加载的上下文对象,知道如果视图被执行,用户就拥有相应的权限!
def options_view(request):
foo = request.context
return {
'foo': foo,
}
使用此设置,您将使用默认的ACLAuthorizationPolicy,并通过 URL Dispatch 为您的对象提供行级权限。另请注意,由于对象在子代上设置了__parent__ 属性,因此该策略将冒泡沿袭,继承父代的权限。只需在 ACL 中添加 DENY_ALL ACE 或编写不使用上下文沿袭的自定义策略即可避免这种情况。
* 更新 *
我已经把这篇文章变成了 Github 上的实际演示。希望它可以帮助某人。
https://github.com/mmerickel/pyramid_auth_demo
* 更新 *
我在这里写了一个关于金字塔认证和授权系统的完整教程:http://michael.merickel.org/projects/pyramid_auth_demo/