安全性

Pyramid 提供可选的声明性安全系统。安全性 Pyramid 分为认证和授权。两个系统通过 principal 标识符。身份验证仅仅是在 request 被解析为一个或多个 principal 标识符。这些标识符表示在请求期间有效的用户和组。授权然后根据 principal 标识符,请求的 permission 和A context .

这个 Pyramid 授权系统可以阻止 view 从基于 authorization policy . 在调用视图之前,授权系统可以使用 request 随着 context 用于确定是否允许访问的资源。下面是它在高层次上的工作方式:

通过修改应用程序以包括 authentication policyauthorization policy . Pyramid 提供了这些策略的各种实现。为了提供最大的灵活性, Pyramid 还允许您创建自定义身份验证策略和授权策略。

启用授权策略

Pyramid 默认情况下不启用任何授权策略。完全匿名的用户可以访问所有视图。为了开始根据安全设置保护视图不被执行,需要启用授权策略。

强制启用授权策略

使用 set_authorization_policy() 方法 Configurator 启用授权策略。

您还必须启用 authentication policy 以便启用授权策略。这是因为授权通常依赖于身份验证。使用 set_authentication_policy() 方法在应用程序安装过程中指定身份验证策略。

例如:

1
2
3
4
5
6
7
8
from pyramid.config import Configurator
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
authn_policy = AuthTktAuthenticationPolicy('seekrit', hashalg='sha512')
authz_policy = ACLAuthorizationPolicy()
config = Configurator()
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(authz_policy)

注解

这个 authentication_policyauthorization_policy 也可以将参数传递给上述各自的方法,如 dotted Python name 值,每个值表示指向在Python模块范围内定义的适当实现全局的点式名称路径。

上面的配置启用了一个策略,该策略比较在请求的环境中传递的“验证票证”cookie的值,该环境包含对单个cookie的引用 userid ,并匹配该用户ID的 principals 反对任何 ACL 在资源树中尝试调用 view .

虽然可以混合和匹配不同的身份验证和授权策略,但使用身份验证策略配置金字塔应用程序时出错,但不使用授权策略,反之亦然。如果这样做,您将在应用程序启动时收到一个错误。

参见

也见 pyramid.authorizationpyramid.authentication 用于授权和身份验证策略的替代实现的模块。

使用权限保护视图

保护一个 view callable 当特定类型的资源成为 context ,您必须通过 permissionview configuration . 权限通常只是字符串,它们没有必需的组合:您可以随意命名权限。

例如,以下视图声明保护名为 add_entry.html 当上下文资源类型为 Blogadd 使用权限 pyramid.config.Configurator.add_view() 应用程序编程接口:

1
2
3
4
5
6
# config is an instance of pyramid.config.Configurator

config.add_view('mypackage.views.blog_entry_add_view',
                name='add_entry.html',
                context='mypackage.resources.Blog',
                permission='add')

等效视图注册包括 add 权限名称可以通过 @view_config 装饰者:

1
2
3
4
5
6
7
from pyramid.view import view_config
from resources import Blog

@view_config(context=Blog, name='add_entry.html', permission='add')
def blog_entry_add_view(request):
    """ Add blog entry code goes here """
    pass

由于这些不同的视图配置语句中的任何一个,如果在正常的应用程序操作中发现视图可调用时,授权策略已就位,则请求用户将需要拥有 add 许可 context 资源以便能够调用 blog_entry_add_view 查看。如果他们不这样做, Forbidden view 将被调用。

设置默认权限

如果没有为视图配置提供权限,则注册的视图将始终由完全匿名的用户执行:忽略任何有效的授权策略。

为了便于配置“默认安全”的应用程序, Pyramid 允许您配置 违约 许可。如果提供了默认权限,则默认权限将用作所有视图注册的权限字符串,而这些注册不是以其他方式命名的 permission 争论。

这个 pyramid.config.Configurator.set_default_permission() 方法支持为应用程序配置默认权限。

注册默认权限时:

  • 如果视图配置将显式 permission ,将忽略该视图注册的默认权限,并使用名为权限的视图配置。
  • 如果视图配置命名权限 pyramid.security.NO_PERMISSION_REQUIRED ,将忽略默认权限,并注册视图 没有 一个权限(使其对所有呼叫者都可用,而不管其凭据如何)。

警告

注册默认权限时, all 观点(甚至) exception view 视图)受权限保护。对于所有真正打算匿名访问的视图,您需要将视图的配置与 pyramid.security.NO_PERMISSION_REQUIRED 许可。

为资源对象分配ACL

当默认 Pyramid authorization policy 确定用户是否拥有与资源相关的特定权限,它检查 ACL 与资源关联。通过添加一个 __acl__ 资源对象的属性。可以在资源上定义此属性 实例 如果您需要实例级安全性,或者可以在资源上定义它 如果您只需要类型级别的安全性。

例如,acl可以通过其类附加到博客的资源:

1
2
3
4
5
6
7
8
9
from pyramid.security import Allow
from pyramid.security import Everyone

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

或者,如果您的资源是持久的,则可以通过 __acl__ AN属性 实例 资源的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from pyramid.security import Allow
from pyramid.security import Everyone

class Blog(object):
    pass

blog = Blog()

blog.__acl__ = [
        (Allow, Everyone, 'view'),
        (Allow, 'group:editors', 'add'),
        (Allow, 'group:editors', 'edit'),
        ]

无论ACL是附加到资源的类还是资源本身的实例,效果都是相同的。在诸如内容管理系统之类的应用程序中,使用ACL(而不仅仅是修饰类)来修饰单个资源实例是很有用的,在这些应用程序中,需要逐对象进行细粒度访问。

动态ACL也可以通过将ACL转换为资源上的可调用文件来实现。这可能允许ACL根据实例的属性动态生成规则。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from pyramid.security import Allow
from pyramid.security import Everyone

class Blog(object):
    def __acl__(self):
        return [
            (Allow, Everyone, 'view'),
            (Allow, self.owner, 'edit'),
            (Allow, 'group:editors', 'edit'),
        ]

    def __init__(self, owner):
        self.owner = owner

警告

写作 __acl__ 因为不鼓励属性,因为 AttributeError 发生在 fgetfset 将被静默解除(这与python一致 getattrhasattr 行为)。对于动态ACL,只需使用可调用文件,如上所述。

ACL的元素

下面是一个示例acl:

1
2
3
4
5
6
7
8
from pyramid.security import Allow
from pyramid.security import Everyone

__acl__ = [
        (Allow, Everyone, 'view'),
        (Allow, 'group:editors', 'add'),
        (Allow, 'group:editors', 'edit'),
        ]

示例acl指示 pyramid.security.Everyone principal——一个特殊的系统定义的principal,字面意思是,每个人都可以查看博客,并且 group:editors 主体可以添加到日志并对其进行编辑。

acl的每个元素都是 ACE 或访问控制项。例如,在上面的代码块中,有三个ace: (Allow, Everyone, 'view')(Allow, 'group:editors', 'add')(Allow, 'group:editors', 'edit') .

任何ace的第一个元素都是 pyramid.security.Allowpyramid.security.Deny ,表示在ACE匹配时要采取的操作。第二个元素是 principal . 第三个参数是权限或权限名称序列。

主体通常是一个用户ID,但是如果您的身份验证系统提供组信息和有效的 authentication policy 编写策略是为了尊重组信息。见 扩展默认身份验证策略 .

ACL中的每个ACE都由授权策略处理 按照acl指定的顺序 . 因此,如果您有这样的ACL:

1
2
3
4
5
6
7
8
from pyramid.security import Allow
from pyramid.security import Deny
from pyramid.security import Everyone

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

默认授权策略将 允许 每个人都有视图权限,即使稍后在ACL中,您有一个拒绝所有人视图权限的ACE。另一方面,如果您有这样的ACL:

1
2
3
4
5
6
7
8
from pyramid.security import Everyone
from pyramid.security import Allow
from pyramid.security import Deny

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

授权策略将拒绝所有人查看权限,即使稍后在ACL中,也有一个允许所有人查看的ACE。

ACE中的第三个参数也可以是权限名序列,而不是单个权限名。因此,不要创建多个ace来表示对单个ace的多个不同权限授予 group:editors 分组,我们可以将其折叠成一个ACE,如下所示。

1
2
3
4
5
6
7
from pyramid.security import Allow
from pyramid.security import Everyone

__acl__ = [
    (Allow, Everyone, 'view'),
    (Allow, 'group:editors', ('add', 'edit')),
    ]

特殊主体名称

特殊主体名称存在于 pyramid.security 模块。它们可以导入以在您自己的代码中用于填充ACL,例如, pyramid.security.Everyone .

pyramid.security.Everyone

从字面上说,每个人,无论什么。这个物体实际上是引擎盖下面的一根绳子 (system.Everyone )每个用户 is 在每个请求期间,即使安全策略不在使用中,主体也会将其命名为“Everyone”。

pyramid.security.Authenticated

具有由当前安全策略确定的凭据的任何用户。您可能会认为它是任何“登录”的用户。这个物体实际上是引擎盖下面的一根绳子 (system.Authenticated

特殊权限

特殊权限名称存在于 pyramid.security 模块。这些可以导入以在ACL中使用。

pyramid.security.ALL_PERMISSIONS

一个物体,字面上表示, all 权限。在像这样的ACL中很有用: (Allow, 'fred', ALL_PERMISSIONS) . 这个 ALL_PERMISSIONS 对象实际上是具有 __contains__ 始终返回的方法 True ,对于所有已知的授权策略,它具有指示给定主体具有系统请求的任何权限的效果。

特殊王牌

方便 ACE 定义为对中所有权限的所有人表示拒绝 pyramid.security.DENY_ALL . 此ace通常用作 last acl的ace显式地导致继承授权策略“停止查找遍历树”(有效地破坏任何继承)。例如,允许 only fred 尽管默认授权策略生效时继承的ACL可能会说,但特定资源的查看权限可能如下所示:

1
2
3
4
from pyramid.security import Allow
from pyramid.security import DENY_ALL

__acl__ = [ (Allow, 'fred', 'view'), DENY_ALL ]

在引擎盖下面, pyramid.security.DENY_ALL ace等于以下值:

1
2
from pyramid.security import ALL_PERMISSIONS
__acl__ = [ (Deny, Everyone, ALL_PERMISSIONS) ]

ACL继承和位置感知

而违约 authorization policy 到位,如果资源对象在作为上下文时没有ACL,则 起源 为ACL咨询。如果该对象没有ACL, its 在我们到达根目录并且没有更多的父目录之前,将为acl(无限)咨询父目录。

为了允许安全机制执行ACL继承,资源对象必须提供 location-awareness . 提供 location-awareness 意味着两件事:资源树中的根对象必须具有 __name__ 属性与A __parent__ 属性。

1
2
3
class Blog(object):
    __name__ = ''
    __parent__ = None

带有 __parent__ 属性与A __name__ 属性被称为 location-aware . 位置感知对象定义 __parent__ 指向其父对象的属性。根对象的 __parent__None .

参见

也见 pyramid.location 用于记录使用位置感知的功能。

参见

也见 位置感知资源 .

更改禁止的视图

什么时候? Pyramid 由于授权拒绝,拒绝视图调用 forbidden 调用视图。开箱即用,这张禁止观看的照片非常清晰。见 更改禁止的视图 在内部 使用钩子 有关如何创建自定义禁止视图以及如何安排在拒绝视图授权时调用该视图的说明。

调试视图授权失败

如果您判断的应用程序不适当地允许或拒绝视图访问,请使用 PYRAMID_DEBUG_AUTHORIZATION 环境变量设置为 1 . 例如:

PYRAMID_DEBUG_AUTHORIZATION=1 $VENV/bin/pserve myproject.ini

当在顶级视图呈现期间发生任何授权时,将向控制台(stderr)记录一条消息,说明ACL在哪个ACE中根据身份验证信息允许或拒绝授权。

也可以在应用程序中启用此行为 .ini 通过设置 pyramid.debug_authorization 关键 true 在应用程序的配置部分中,例如:

1
2
3
[app:main]
use = egg:MyProject
pyramid.debug_authorization = true

打开此调试标志后,发送到浏览器的响应在其主体中还将包含安全调试信息。

调试强制授权失败

这个 pyramid.request.Request.has_permission() API用于强制检查视图函数中的安全性。它返回有效布尔值的对象实例。但是这些东西不是生的 TrueFalse 对象,并向其附加有关允许或拒绝权限的原因的信息。对象将是 pyramid.security.ACLAllowedpyramid.security.ACLDeniedpyramid.security.Allowedpyramid.security.Denied ,如中所述 pyramid.security . 至少,这些对象将具有 msg 属性,该字符串指示拒绝或允许权限的原因。当调用 has_permission() 失败往往是有用的。

扩展默认身份验证策略

金字塔附带一些内置的身份验证策略,可在应用程序中使用。见 pyramid.authentication 对于可用的策略。它们在跟踪请求之间的身份验证凭据的机制上有所不同,但是它们都以基本相同的方式与应用程序交互。

上面你了解到 为资源对象分配ACL .每个 principal 用于 ACL 与从返回的列表匹配 pyramid.interfaces.IAuthenticationPolicy.effective_principals() . 同样地, pyramid.request.Request.authenticated_userid() 地图到 pyramid.interfaces.IAuthenticationPolicy.authenticated_userid() .

您可以通过子类化默认身份验证策略来控制这些值。例如,下面我们将 pyramid.authentication.AuthTktAuthenticationPolicy 并在确认 userid 有效以避免盲目信任cookie中的值(如果cookie仍然有效,但用户已删除其帐户怎么办?)我们就用那个 userid 增补 effective_principals 包含有关该用户的组和其他状态的信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pyramid.authentication import AuthTktAuthenticationPolicy

class MyAuthenticationPolicy(AuthTktAuthenticationPolicy):
    def authenticated_userid(self, request):
        userid = self.unauthenticated_userid(request)
        if userid:
            if request.verify_userid_is_still_valid(userid):
                return userid

    def effective_principals(self, request):
        principals = [Everyone]
        userid = self.authenticated_userid(request)
        if userid:
            principals += [Authenticated, str(userid)]
        return principals

在大多数情况下 authenticated_userideffective_principals 是特定的应用程序,而 unauthenticated_useridrememberforget 是通用的,主要关注连续请求之间的数据传输和序列化。

创建您自己的身份验证策略

Pyramid 提供了许多有用的现成安全策略(请参见 pyramid.authentication )但是,当您想要控制用户身份验证方式的“水平和垂直”时,通常需要创建自己的身份验证策略。这样做是为了创建实现以下接口的某个对象的实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class IAuthenticationPolicy(object):
    """ An object representing a Pyramid authentication policy. """

    def authenticated_userid(self, request):
        """ Return the authenticated :term:`userid` or ``None`` if
        no authenticated userid can be found. This method of the
        policy should ensure that a record exists in whatever
        persistent store is used related to the user (the user
        should not have been deleted); if a record associated with
        the current id does not exist in a persistent store, it
        should return ``None``.
        """

    def unauthenticated_userid(self, request):
        """ Return the *unauthenticated* userid.  This method
        performs the same duty as ``authenticated_userid`` but is
        permitted to return the userid based only on data present
        in the request; it needn't (and shouldn't) check any
        persistent store to ensure that the user record related to
        the request userid exists.

        This method is intended primarily a helper to assist the
        ``authenticated_userid`` method in pulling credentials out
        of the request data, abstracting away the specific headers,
        query strings, etc that are used to authenticate the request.
        """

    def effective_principals(self, request):
        """ Return a sequence representing the effective principals
        typically including the :term:`userid` and any groups belonged
        to by the current user, always including 'system' groups such
        as ``pyramid.security.Everyone`` and
        ``pyramid.security.Authenticated``.
        """

    def remember(self, request, userid, **kw):
        """ Return a set of headers suitable for 'remembering' the
        :term:`userid` named ``userid`` when set in a response.  An
        individual authentication policy and its consumers can
        decide on the composition and meaning of **kw.
        """

    def forget(self, request):
        """ Return a set of headers suitable for 'forgetting' the
        current user on subsequent requests.
        """

这样做之后,可以将此类的实例传递到 set_authentication_policy 方法在配置时使用它。

创建您自己的授权策略

授权策略是一种允许或拒绝用户通过身份验证后访问的策略。大多数 Pyramid 应用程序将使用默认值 pyramid.authorization.ACLAuthorizationPolicy .

但是,在某些情况下,使用不同于默认的授权策略是很有用的 ACLAuthorizationPolicy . 例如,可能需要构造一个备用授权策略,允许应用程序使用不涉及 ACL 物体。

Pyramid 只提供一个默认授权策略,因此如果您想使用其他策略,则需要创建自己的策略。创建和使用您自己的授权策略是创建实现以下接口的对象的实例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class IAuthorizationPolicy(Interface):
    """ An object representing a Pyramid authorization policy. """
    def permits(context, principals, permission):
        """ Return an instance of :class:`pyramid.security.Allowed` if any
        of the ``principals`` is allowed the ``permission`` in the current
        ``context``, else return an instance of
        :class:`pyramid.security.Denied`.
        """

    def principals_allowed_by_permission(context, permission):
        """ Return a set of principal identifiers allowed by the
        ``permission`` in ``context``.  This behavior is optional; if you
        choose to not implement it you should define this method as
        something which raises a ``NotImplementedError``.  This method
        will only be called when the
        ``pyramid.security.principals_allowed_by_permission`` API is
        used."""

这样做之后,可以将此类的实例传递到 set_authorization_policy 方法在配置时使用它。

反对秘密分享的告诫

金字塔的各个组成部分都需要一个“秘密”。例如, authentication policy 下面使用一个秘密值 seekrit ::

authn_policy = AuthTktAuthenticationPolicy('seekrit', hashalg='sha512')

A session factory 还需要一个秘密:

my_session_factory = SignedCookieSessionFactory('itsaseekreet')

对于多个金字塔子系统,使用相同的秘密是很有诱惑力的。例如,您可能会尝试使用该值 seekrit 作为上面定义的身份验证策略和会话工厂的秘密。这是一个坏主意,因为在这两种情况下,这些秘密都被用来签署数据的有效负载。

如果您将同一个秘密用于应用程序的两个不同部分进行签名,则可能会允许攻击者对所选明文进行签名,从而允许攻击者控制有效负载的内容。在两个不同的子系统中重新使用秘密可能会使签名的安全性降低到零。在攻击者可能提供所选纯文本的不同上下文中,不应重复使用密钥。

防止跨站点请求伪造攻击

Cross-site request forgery 攻击是一种现象,登录到您的网站的用户可能不小心加载一个URL,因为它是从攻击者的网站链接或嵌入的。如果URL是一个可以修改或删除数据的URL,那么后果可能很严重。

通过向浏览器发出一个唯一的令牌,然后要求它出现在所有潜在的不安全请求中,可以避免大多数攻击。 Pyramid 提供创建和检查CSRF令牌的工具。

默认情况下 Pyramid 带有基于会话的CSRF实现 pyramid.csrf.SessionCSRFStoragePolicy . 要使用它,必须首先启用 session factory 如上所述 使用默认会话工厂使用备用会话工厂 . 或者,您可以使用基于cookie的实现 pyramid.csrf.CookieCSRFStoragePolicy 这给了一些额外的灵活性,因为它不需要为每个用户提供会话。您还可以定义自己的 pyramid.interfaces.ICSRFStoragePolicy 并将其注册到 pyramid.config.Configurator.set_csrf_storage_policy() 指令。

例如:

from pyramid.config import Configurator

config = Configurator()
config.set_csrf_storage_policy(MyCustomCSRFPolicy())

使用 csrf.get_csrf_token 方法

要获取当前的CSRF令牌,请使用 pyramid.csrf.get_csrf_token 方法。

from pyramid.csrf import get_csrf_token
token = get_csrf_token(request)

这个 get_csrf_token() 方法接受单个参数:请求。它返回一个CSRF 令牌 字符串。如果 get_csrf_token()new_csrf_token() 以前为此用户调用过,则将返回现有令牌。如果此用户以前没有CSRF令牌,那么将在会话中设置一个新令牌并返回。新创建的令牌将是不透明的和随机的。

使用 get_csrf_token 模板中的全局

模板具有 get_csrf_token() 方法插入到它们的全局中,这允许您在不修改视图代码的情况下获取当前标记。此方法不接受任何参数并返回CSRF令牌字符串。您可以使用返回的令牌作为表单中隐藏字段的值,该表单向需要提升权限的方法发送消息,或者在Ajax请求中将其作为请求头提供。

例如,将CSRF令牌包含为隐藏字段:

<form method="post" action="/myview">
  <input type="hidden" name="csrf_token" value="${get_csrf_token()}">
  <input type="submit" value="Delete Everything">
</form>

或者将其作为头包含在jquery ajax请求中:

var csrfToken = "${get_csrf_token()}";
$.ajax({
  type: "POST",
  url: "/myview",
  headers: { 'X-CSRF-Token': csrfToken }
}).done(function() {
  alert("Deleted");
});

然后,接收请求的URL的处理程序应要求提供正确的CSRF令牌。

使用 csrf.new_csrf_token 方法

要显式创建新的CSRF令牌,请使用 csrf.new_csrf_token() 方法。这与 csrf.get_csrf_token() 因为它清除任何现有的CSRF令牌,创建一个新的CSRF令牌,将令牌设置为用户,并返回令牌。

from pyramid.csrf import new_csrf_token
token = new_csrf_token(request)

注解

无法从模板强制新的CSRF令牌。如果要重新生成CSRF令牌,请在视图代码中执行该操作,并将新令牌作为上下文的一部分返回。

手动检查CSRF令牌

在请求处理代码中,您可以使用 pyramid.csrf.check_csrf_token() . 如果令牌有效,它将返回 True ,否则会升高 HTTPBadRequest . 或者,您可以指定 raises=False 把支票退了 False 而不是提出例外。

默认情况下,它检查名为 csrf_token 或一个名为 X-CSRF-Token .

from pyramid.csrf import check_csrf_token

def myview(request):
    # Require CSRF Token
    check_csrf_token(request)

    # ...

自动检查CSRF令牌

1.7 新版功能.

Pyramid 支持使用RFC2616定义的不安全方法对请求自动检查CSRF令牌。可以手动检查任何其他请求。对于使用 pyramid.config.Configurator.set_default_csrf_options() 指令。例如:

from pyramid.config import Configurator

config = Configurator()
config.set_default_csrf_options(require_csrf=True)

可以使用 require_csrf 查看选项。一个值 TrueFalse 将覆盖默认设置 set_default_csrf_options . 例如:

@view_config(route_name='hello', require_csrf=False)
def myview(request):
    # ...

当CSRF检查激活时,用于查找提供的CSRF令牌的令牌和头将 csrf_tokenX-CSRF-Token ,分别,除非另有规定 set_default_csrf_options . 将根据中的值检查令牌 request.POST 这是提交的表单主体。如果此值不存在,则将检查标题。

除了基于令牌的CSRF检查之外,如果请求使用HTTPS,那么自动CSRF检查还将检查请求的引用,以确保它与受信任的来源之一匹配。默认情况下,唯一受信任的源是当前主机,但是可以通过设置配置其他源 pyramid.csrf_trusted_origins to a list of domain names (and ports if they are non-standard). If a host in the list of domains starts with a . 这样就允许所有子域以及没有 . .

如果CSRF检查失败,则 pyramid.exceptions.BadCSRFTokenpyramid.exceptions.BadCSRFOrigin 将引发异常。此异常可能由 exception view 但是,默认情况下,会导致 400 Bad Request 正在向客户端发送响应。

使用视图谓词检查CSRF令牌

1.7 版后已移除: 使用 require_csrf 选项或读取 自动检查CSRF令牌 取而代之的是 pyramid.exceptions.BadCSRFToken 引发异常。

要为特定视图要求有效的CSRF令牌,一个方便的方法是包括 check_csrf=True 作为视图谓词。见 pyramid.config.Configurator.add_view() .

@view_config(request_method='POST', check_csrf=True, ...)
def myview(request):
    # ...

注解

CSRF令牌的不匹配被视为任何其他谓词未命中,并且谓词系统在找不到视图时会引发 HTTPNotFound 而不是 HTTPBadRequest 如此 check_csrf=True 行为不同于呼叫 pyramid.csrf.check_csrf_token() .