存储项目的金字塔授权

vir*_*tor 19 python policy authorization pyramid

我正在尝试创建一个将"项目"所有权考虑在内的授权策略.例如,一些用户X"拥有"项目A,B,C.这些是通过URL访问的/item/{item}/some_options.

如何获取有关{item}授权策略对象的信息(permit()调用)?将附加信息放入上下文中是一个好主意(我只做基于路由的路由).我该怎么办?

Mic*_*kel 51

您可以使用ACLAuthorizationPolicy与URL Dispatch结合使用为此目的设计的自定义资源树来执行此操作.

例如,您拥有Foo对象的权限和Bar对象的权限.可以使用url遍历资源树来找到这些ACL:

/foos/{obj}
/bars/{obj}
Run Code Online (Sandbox Code Playgroud)

然后,您的资源树将成为权限层次结构,您可以在树中的任何位置放置__acl__资源对象:

root                       (Root)
|- foos                    (FooContainer)
|  `- {obj}                (Foo)
`- bars                    (BarContainer)
   `- {obj}                (Bar)
Run Code Online (Sandbox Code Playgroud)

您可以在资源树中表示此层次结构:

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')
    ]
Run Code Online (Sandbox Code Playgroud)

使用这样的设置,您可以将路由模式映射到资源树:

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}')
Run Code Online (Sandbox Code Playgroud)

您还需要将路线映射到特定视图:

config.add_view(route_name='item_options', view='.views.options_view',
                permission='view', renderer='item_options.mako')
Run Code Online (Sandbox Code Playgroud)

太好了,现在我们可以定义我们的视图并使用加载的上下文对象,知道如果执行了视图,则用户具有相应的权限!

def options_view(request):
    foo = request.context
    return {
        'foo': foo,
    }
Run Code Online (Sandbox Code Playgroud)

使用此设置,您使用的是默认设置ACLAuthorizationPolicy,并且您使用URL Dispatch为对象提供行级权限.另请注意,由于对象__parent__在子项上设置了属性,因此策略将冒充谱系,继承父项的权限.只需DENY_ALL在ACL中放置ACE,或者编写不使用上下文沿袭的自定义策略,就可以避免这种情况.

*更新* 我已将此帖子转换为Github上的实际演示.希望它可以帮助某人. https://github.com/mmerickel/pyramid_auth_demo

*更新* 我在这里写了一篇关于金字塔认证和授权系统的完整教程:http://michael.merickel.org/projects/pyramid_auth_demo/