金字塔“每个对象”权限

Mar*_*ann 2 python acl pyramid

我正在尝试为我正在构建的应用程序工具箱创建一个安全系统。我以前有一个 acl,但问题是我无法在基于应用程序的级别上进行控制。

我认为下图描述了我如何在数据库中设置它。 数据库ACL布局图

基本上,我认为我需要的是将应用程序 GUID 传递给函数groupfinder(),但我不确定应该如何处理这个问题。有人有什么想法吗?

Mic*_*kel 5

groupfinder金字塔中的 和旨在context factory单独且隔离地运行。前者用于定义“当前用户”,后者用于定义“当前资源”。这两项最终结合起来permission通过授权策略的permits功能来判断“当前用户”是否有“权限”操作这个“资源”。

  1. 负责groupfinder识别用户。这意味着将它们转换为一组稍后可以使用的主体。

  2. 确定context factory当前资源(上下文)...因此每个 url 通常应该不同(记住 URL 中的 R 是资源),因此 url 通常定义资源。

  3. 附加到 url 的视图定义了permission所需的内容(对于视图执行的操作)。

这里的第二步是人们来到金字塔时最难理解的。如何为每个 URL 定义此资源?url 调度教程 [1] 中对此进行了介绍,但我将在这里快速解释。

正如我上面所说,每个路由通常代表一个资源,因此我们可以通过为该路由定义一个对象将其放入代码中。这是通过factory参数来完成的config.add_route(..., factory=...),它可以使用路由做很多事情来确定当前资源是什么。

def page_factory(request):
    # I'm attached to a page so I can grab the matchdict
    pageid = request.matchdict['pageid']
    page = request.db.query(Page).get(pageid)
    if page is None:
        raise HTTPNotFound
    return page

config.add_route('page', '/pages/{pageid}', factory=page_factory)
Run Code Online (Sandbox Code Playgroud)

此代码片段定义了一个带有页面工厂的路由,并且附加到该路由的每个视图都将将该页面作为上下文 ( request.context)。

这里的对象Page有一个 ACL,定义允许哪些用户/组(主体)对其执行哪些操作(权限)。

class Page(Base):
    __tablename__ = 'page'

    # a bunch of columns

    def __acl__(self):
        return [
            (Allow, f'app:{self.app.id} user:{self.owner_id}', 'edit'),
            (Allow, f'app:{self.app.id}', 'read'),
        ]
Run Code Online (Sandbox Code Playgroud)

假设此页面附加到 app1,我们可以轻松定义一个 groupfinder,表示 app1 中的任何人都可以读取它:

def groupfinder(userid, request):
    user = request.db.query(User).get(userid)
    if user is not None:
        principals = []
        for app in user.apps:
            principals += [
                f'app:{app.id}',
                f'app:{app.id} user:{user.id}',
            ]
            for group in app.groups:
                principals += [f'app:{app.id} group:{group.id}']
        return principals
Run Code Online (Sandbox Code Playgroud)

groupfinder 不了解页面,但它以足够的粒度描述用户,以便页面可以将用户与其允许的操作相匹配。

[1] https://docs.pylonsproject.org/projects/pyramid/en/1.9-branch/tutorials/wiki2/authorization.html