在Pyramid中实现认证/授权

1 投票
1 回答
788 浏览
提问于 2025-04-17 13:30

我按照文档中的说明 组级安全
写了这些代码:

def groupfinder(userid, request):
    print '#'*80
    print userid
    role = DBSession.query(Role)....

    if role.name == "Admin":
        return ['g:admin']


class RootFactory(object):
        __acl__ = [
            (Allow, Everyone, 'view'),
            (Allow, Authenticated, 'edit'),
            (Allow, 'g:admin', 'admin')
        ]

        def __init__(self, request):
            pass


authn_policy = AuthTktAuthenticationPolicy(
    settings['auth.secret'],
    callback=groupfinder,
)

它是可以工作的,但每次加载页面时都会重复查询数据库
难道应该在用户第一次登录时就返回权限吗?
还是说我做错了什么...

我该如何在像mako这样的模板中知道权限“g:admin”呢?

1 个回答

6

你的 groupfinder 现在有一个小问题。它应该总是返回一个列表,只要用户是有效的。只有在没有用户的情况下,它才应该返回 None。现在你只在用户是管理员时返回列表,所以普通用户永远不会被识别。

def groupfinder(userid, request):
    print '#'*80
    print userid
    role = DBSession.query(Role)....

    if role is not None:
        principals = []
        if role.name == "Admin":
            principals.append('g:admin')
        return principals

注意,我们总是返回一个列表,除非 roleNone

接下来,你问到了性能问题。Pyramid 不会尝试缓存任何东西。不过,你可以自己轻松处理这个问题。通常的做法是在你的 request 对象上添加一个缓存的(具体化的)属性,里面存放 roleuser。这样每次调用 groupfinder 时,你就可以使用缓存的 role,而不是再次查询它。这个模式可以在 这里 查看。

我怎么知道在像 mako 这样的模板中权限 "g:admin" 的情况?

其实 'g:admin' 在 Pyramid 的认证术语中是一个 主体。'admin'(你访问控制条目的第三个元素)是 权限。主体被视为实现细节,只是帮助我们将事物映射到权限上。最终,我们在处理访问/授权时,真正关心的只是权限。

要在你的模板中查看用户是否拥有该权限,你可以使用 pyramid.security.has_permission('admin', request.context, request)。你可以用任何具有 __acl__ 的对象替换 request.context,但在这个场景中,request.context 将是你的 RootFactory(这正是你想要的)。

撰写回答