Tuesday, April 3, 2012

Pyramid的权限管理


Pyramid提供了一种声明式的权限管理,可以按照一定的授权策略保护view,以保证只有经过认证的用户才能访问应用。在Pyramid中,权限管理体系被明确的分成了认证和授权两个部分。

认证系统将request中的身份证明转化成一个或多个系统能识别的主体标识。这些表示代表了request中当前生效的用户、组信息。

授权系统则根据得到的主体标识、视图配置、上下文决定是否有访问权限。

一、Pyramid权限处理流程

1. 用户用过一个特定的URL访问应用,因此在应用中生成一个request。
2. 基于这个request的信息,通过resource定位找到一个上下文(context)(不论是漫游还是URL分发)。
3. 通过视图定位找到一个合适的视图,
4. 如果认证策略生效,将由此与request生成几个主体(principal)的标识。
5. 如果授权策略生效,并且视图配置中定义定义了permission参数,将由这它们以及上下文、主体标识来共同决定是否有权访问这个视图。
6. 如果授权成功,则调用视图。
7. 如果授权失败,则调用forbidden视图。


二、权限配置声明

1. 启动配置

在Pyramid中,授权系统依赖于认证系统,要启动授权系统,必须先启动认证系统。如下例

from pyramid.config import Configurator
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
authentication_policy = AuthTktAuthenticationPolicy('seekrit')
authorization_policy = ACLAuthorizationPolicy()
config = Configurator()
config.set_authentication_policy(authentication_policy)
config.set_authorization_policy(authorization_policy)

2. view config配置
在项目启动时配置了认证策略、授权策略之外,还需要在每个view的配置中加入permission参数。例如:
config.add_view(’mypackage.views.blog_entry_add_view’,
                name=’add_entry.html’,
                context=’mypackage.resources.Blog’,
                permission=’add’)

也可以加在view_config中,例如:
@view_config(context=Blog, name=’add_entry.html’, permission=’add’)

这里的"add"是一个在ACL中定义的字符串,可以更换成任何记得住的名字。

3. 默认权限

如果视图数量比较多,且权限大多类似的情况下,可以定义一个默认权限,如调用Configurator中下面的方法:

pyramid.config.Configurator.set_default_permission() 

定义了默认权限之后,没有加入permission参数的所有视图都将默认带有该权限。开发者也可以加入该参数来变更为其他权限。如果要让视图变成无权限,则需要设置permission为pyramid.security.NO_PERMISSION_REQUIRED。


三、ACL

1. ACL定义

在Pyramid中,可以在类中定义ACL,也可以在一个具体的实例中定义ACL。例如:

class Blog(object): __acl__ = [
        (Allow, Everyone, ’view’),
        (Allow, ’group:editors’, ’add’),
        (Allow, ’group:editors’, ’edit’),
        ]

class Blog(object): pass
blog = Blog()
blog.__acl__ = [
        (Allow, Everyone, ’view’),
        (Allow, ’group:editors’, (’add’, ’edit’)),
        ]

这两种定义都是可行的,只不过他们并不等同,其作用范围是不一样的。

2. ACL元素介绍

在上面的例子中,我们可以看到,ACL就是一个由三元组(ACE,access control emtry)组成的列表。其中每个元祖的第一个参数为固定的Allow/Deny,第二个参数为主体标识,第三个参数为权限名或权限名元组,用在permission参数中。如(Allow, Everyone, ’view’)即为所有人均具有‘view’(这里是查看的意思,不是那个视图噢)这个权限。(Allow, ’group:editors’, ’add’)表明所有editors组的人员均有新增权限。

ACL的定义是有前后顺序的,因此,不好的定义很可能会导致后面的ACE不起作用,如

__acl__ = [
    (Allow, Everyone, ’view’),
    (Deny, Everyone, ’view’),
    ]

后面的Deny永远不起作用。所有用户均有查看权限。而

__acl__ = [
    (Deny, Everyone, ’view’),
    (Allow, Everyone, ’view’),
    ]

则所有用户都没有查看权限

3. 一些特殊的主体

为了使用上的便利,在Pyramid.security中定义了一些特殊的主体,如:

pyramid.security.Everyone,所有人员

pyramid.security.Authenticated,已登录人员

4. 特殊的权限

pyramid.security.ALL_PERMISSIONS,包含任何权限

5. 特殊的ACE

pyramid.security.DENY_ALL,等同于(Deny, Everyone, ALL_PERMISSIONS)

6. ACL查找方法

当一个resource对象作为上下文时,如果它自身没有带ACL信息,则会继续查找其父节点的ACL信息,层层向上,直到根节点。(这时resource树必须是位置感知的。)

四、高级用法

1. 变更forbidden视图

在Configurator中调用add_forbidden_view方法:
from helloworld.views import forbidden_view
from pyramid.httpexceptions import HTTPForbidden

config.add_forbidden_view(forbidden_view)

2. 权限配置调试

变更development.ini文件
[app:main]
use = egg:MyProject
pyramid.debug_authorization = true

3. has_permission方法

Pyramid提供了pyramid.security.has_permission()这样一个方法来判断是否有权限,它将返回 pyramid.security.ACLAllowed, pyramid.security.ACLDenied, pyramid.security.Allowed, 或 pyramid.security.Denied。


No comments:

Post a Comment