【问题标题】:Pyramid authorization for stored items存储物品的金字塔授权
【发布时间】:2011-08-11 07:44:15
【问题描述】:

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

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

【问题讨论】:

    标签: python authorization policy pyramid


    【解决方案1】:

    您可以通过使用为此目的设计的自定义资源树将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/

    【讨论】:

    • 建议使您的教程更加有用:最好在这里讨论您对 Container 的使用,因为我不确定在使用数据库连接时如何构建资源树。看了教程后找到了这个答案,很有帮助。
    猜你喜欢
    • 2014-07-23
    • 2021-01-03
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 2011-06-22
    • 1970-01-01
    • 2019-09-14
    相关资源
    最近更新 更多