[英]Pyramid “per object” permissions
我正在尝试为我正在构建的应用程序工具箱创建一个安全系统。 我以前有一个acl,但是问题是我无法在基于应用程序的级别上进行控制。
基本上,我认为我需要将应用程序GUID传递给groupfinder()
函数 ,但我不确定应该如何处理。 有人有什么想法吗?
Pyramid中的groupfinder
和context factory
旨在独立运行和隔离。 前者用于定义“当前用户”,后者用于定义“当前资源”。 最后,通过授权策略的permits
功能将这两项与permission
组合在一起,以确定“当前用户”是否具有“许可”才能对该“资源”进行操作。
groupfinder
器负责识别用户。 这意味着将它们转换为一组供以后使用的主体。
context factory
确定当前资源(上下文)...因此,每个URL通常应该不同(记住URL中的R是资源),因此该URL通常定义了资源。
附加到url的视图定义了所需的permission
(用于由视图执行的操作)。
第2步是来到金字塔时人们最难以理解的地方。 如何为每个URL定义此资源? 它在url分发教程[1]中进行了介绍,但是我将在此处快速进行解释。
就像我在上面说的那样,每条路由通常代表一个资源,因此我们可以通过为该路由定义一个对象将其放入代码中。 这是通过config.add_route(..., factory=...)
的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)
此代码段定义了具有页面工厂的路由,并且此路由所附加的每个视图都将页面作为上下文( request.context
)。
这里的Page
对象具有一个ACL,该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'),
]
假设此页面已附加到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
分组查找器不了解页面,但它以足够的粒度描述用户,以使页面可以将其与其允许的操作进行匹配。
[1] https://docs.pylonsproject.org/projects/pyramid/zh-CN/1.9-branch/tutorials/wiki2/authorization.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.