Kan*_*ane 6 security authentication pylons authorization pyramid
我正在尝试在我的网站上实现金字塔的安全功能,但我在确定如何使用它时遇到了一些麻烦.
我一直在阅读本教程和本例以及Pyramid文档,我无法弄清楚如何为单页ID实现授权策略.
例如,我有以下URL方案:
/pages
/pages/12
Run Code Online (Sandbox Code Playgroud)
/pages显然列出了可用的页面/pages/:id,您可以在该页面上阅读/评论.
我读过的文档/示例表明,您可以通过提供包含groupfinder组列表的回调来实现组级ACS .如editor,admin等
我怎样才能根据页面ID使用组权限而不是权限?
在上面的URL方案中,当用户浏览时,/pages他们必须登录.当他们浏览时/pages/:id,他们必须有权查看该特定ID.或者,他们必须是该页面的所有者.
与评论相同.在/page/:id页面上,他们可能已被授予查看页面的权限,但不对其进行评论.
这里的基本原则是Pyramid的安全机制在当前上下文中检查ACL.在这种情况下,您的页面将是要使用的逻辑上下文.第一步是为页面设置上下文工厂.假设您正在使用SQLAlchemy和URL分派,这很容易做到.注册您的路线,如下所示:
config.add_route('page', '/pages/{id:\d+}', factory=page_factory)
Run Code Online (Sandbox Code Playgroud)
在路径的路径中有一个小技巧,使得金字塔检查页面ID必须是一个数字,因此您不必自己检查.请注意对*page_factory*方法的引用.让我们现在定义:
def page_factory(request):
return DBSession.query(Page).get(int(request.matchdict['id']))
Run Code Online (Sandbox Code Playgroud)
这将从路径中获取页面ID,并使用它来查找数据库中的页面.请注意,我们不会检查id是否可以在这里转换为整数:我们可以自行解决,因为路由已经直接检查了.
下一步是在页面上设置ACL.最简单的方法是为您的Page class 添加一个acl属性:
from pyramid import security
class Page(BaseObject):
@property
def __acl__(self):
return [(security.Allow, self.userid, 'view')]
Run Code Online (Sandbox Code Playgroud)
此ACL告诉金字塔,只允许具有存储在page.userid中的id的用户查看该页面.这里要认识到的重要一点是每个页面的ACL都是不同的:它是根据数据库中的信息分别为每个页面生成的; 在这种情况下使用self.userid.
您现在可以在视图上使用查看权限:
@view_config(route_name='page', context=Page, permission='view')
def page_view(context, request):
return 'I can see!'
Run Code Online (Sandbox Code Playgroud)
此示例对页面具有非常小的ACL,但您可以扩展它以满足您的需要.
还要注意view_config的context = Page参数:这告诉金字塔这个视图应该只用于上下文是一个Page.如果上下文工厂(此示例中为page_factory)未找到匹配的页面,则它将返回None而不是Page实例,因此金字塔不会使用此视图.因此,金字塔将自动产生未发现的错误.
出于本次讨论的目的,我假设您正在使用 SQLAlchemy 与数据库进行交互。
如果您config.add_route('pages', '/pages/{id}')的 中有__init__.py,您可以添加自定义工厂来替换/补充您的默认 ACL。例如:
您当前的 ACL 可能如下所示:
class RootFactory(object):
__acl__ = [
(Allow, Everyone, 'view'),
(Allow, Authenticated, 'auth'),
]
def __init__(self, request):
self.request = request
Run Code Online (Sandbox Code Playgroud)
这将允许经过身份验证的用户使用“auth”权限访问任何视图,并且允许访问您网站的任何人使用“view”权限访问任何视图。
通过使用自定义工厂,您可以绕过 RootFactory 或对其进行补充。
要绕过,请将原始 config.add_route 更改为 -->config.add_route('pages', '/pages/{id}', factory=PageFactory)并创建一个 PageFactory 类,如下所示:
class PageFactory(object):
__acl__ = [
(Allow, Everyone, 'view'),
(Allow, Authenticated, 'auth'),
]
def __init__(self, request):
self.request = request
from pyramid.security import authenticated_userid
user_id = authenticated_userid(self.request)
thispage = DBSession.query(Page).filter(Page.id==self.request.matchdict['id']).first()
if thispage.user_id == user_id:
## Pyramid allows Everyone, Authenticated, and authenticated_userid
## (each of these is known as a Principal) to be in the second
## position of the ACL tuple
acl.append((Allow, user_id, 'edit'))
Run Code Online (Sandbox Code Playgroud)
这是假设您的视图具有permission='edit'其参数之一。
现在,如果您想使用 RootFactory 并用您的自定义工厂对其进行补充,那么您不必重复自己,只需保留 RootFactory (如我在本文开头所示),并从 RootFactory 类继承, 像这样:
class PageFactory(RootFactory):
@property
def __acl__(self):
acl = super(PageFactory, self).__acl__[:] ##[:] creates a copy
from pyramid.security import authenticated_userid
user_id = authenticated_userid(self.request)
thispage = DBSession.query(Page).filter(Page.id==self.request.matchdict['id']).first()
if thispage.user_id == user_id:
acl.append((Allow, user_id, 'edit'))
return acl
Run Code Online (Sandbox Code Playgroud)
顺便说一句,groupfinder非常有用,因为这样您可以简单地将用户放入组中,例如“admin”,并且 admin 组中的所有用户都可以访问您可能想要的视图,并且不需要 Factory,只需要一个groupfinder 返回当前用户的组列表。唉,我离题了,因为那不是你想要做的。希望这能回答您的问题。permission='whatever'permission='whateverelse'
| 归档时间: |
|
| 查看次数: |
581 次 |
| 最近记录: |