ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 02.01.2026
Просмотров: 2722
Скачиваний: 0
27. SECURITY
27.11 Debugging Imperative Authorization Failures
The pyramid.security.has_permission() API |
is used to check security within |
||||||||||
view |
functions |
imperatively. |
It |
returns |
instances of |
objects that are effectively booleans. |
|||||
But these objects are not |
raw |
True |
or |
False |
objects, |
and have |
information |
at- |
|||
tached to |
them |
about why |
the |
permission |
was allowed or |
denied. |
The object |
will |
|||
be |
one |
of |
pyramid.security.ACLAllowed, |
pyramid.security.ACLDenied, |
|||||||
pyramid.security.Allowed, or pyramid.security.Denied, as documented in pyramid.security. At the very minimum these objects will have a msg attribute, which is a string indicating why the permission was denied or allowed. Introspecting this information in the debugger or via print statements when a call to has_permission() fails is often useful.
27.12 Creating Your Own Authentication Policy
Pyramid ships with a number of useful out-of-the-box security policies (see pyramid.authentication). However, creating your own authentication policy is often necessary when you want to control the “horizontal and vertical” of how your users authenticate. Doing so is a matter of creating an instance of something that implements the following interface:
1 class IAuthenticationPolicy(object):
2""" An object representing a Pyramid authentication policy. """
3
4def authenticated_userid(self, request):
5""" Return the authenticated userid or ‘‘None‘‘ if no
6authenticated userid can be found. This method of the policy
7 should ensure that a record exists in whatever persistent store is 8 used related to the user (the user should not have been deleted); 9 if a record associated with the current id does not exist in a
10 persistent store, it should return ‘‘None‘‘."""
11
12def unauthenticated_userid(self, request):
13""" Return the *unauthenticated* userid. This method performs the
14same duty as ‘‘authenticated_userid‘‘ but is permitted to return the
15userid based only on data present in the request; it needn’t (and
16shouldn’t) check any persistent store to ensure that the user record
17related to the request userid exists."""
18
19def effective_principals(self, request):
20""" Return a sequence representing the effective principals
21including the userid and any groups belonged to by the current
22user, including ’system’ groups such as
302
27.13. CREATING YOUR OWN AUTHORIZATION POLICY
23‘‘pyramid.security.Everyone‘‘ and
24‘‘pyramid.security.Authenticated‘‘. """
25
26def remember(self, request, principal, **kw):
27""" Return a set of headers suitable for ’remembering’ the
28principal named ‘‘principal‘‘ when set in a response. An
29individual authentication policy and its consumers can decide
30on the composition and meaning of **kw. """
31
32def forget(self, request):
33""" Return a set of headers suitable for ’forgetting’ the
34current user on subsequent requests. """
After you do so, you can pass an instance of such a class into the set_authentication_policy method configuration time to use it.
27.13 Creating Your Own Authorization Policy
An |
authorization |
policy is |
a policy |
that allows or |
denies |
access |
after a |
user |
has been |
authenticated. |
Most |
Pyramid applications |
will |
use the |
default |
pyramid.authorization.ACLAuthorizationPolicy.
However, in some cases, it’s useful to be able to use a different authorization policy than the default ACLAuthorizationPolicy. For example, it might be desirable to construct an alternate authorization policy which allows the application to use an authorization mechanism that does not involve ACL objects.
Pyramid ships with only a single default authorization policy, so you’ll need to create your own if you’d like to use a different one. Creating and using your own authorization policy is a matter of creating an instance of an object that implements the following interface:
1 class IAuthorizationPolicy(object):
2 """ An object representing a Pyramid authorization policy. """
3def permits(self, context, principals, permission):
4""" Return ‘‘True‘‘ if any of the ‘‘principals‘‘ is allowed the
5‘‘permission‘‘ in the current ‘‘context‘‘, else return ‘‘False‘‘
6"""
7
8def principals_allowed_by_permission(self, context, permission):
9""" Return a set of principal identifiers allowed by the
10 ‘‘permission‘‘ in ‘‘context‘‘. This behavior is optional; if you
303
27. SECURITY
11choose to not implement it you should define this method as
12something which raises a ‘‘NotImplementedError‘‘. This method
13will only be called when the
14‘‘pyramid.security.principals_allowed_by_permission‘‘ API is
15used."""
After you do so, you can pass an instance of such a class into the set_authorization_policy method at configuration time to use it.
304
CHAPTER
TWENTYEIGHT
COMBINING TRAVERSAL AND URL DISPATCH
When you write most Pyramid applications, you’ll be using one or the other of two available resource location subsystems: traversal or URL dispatch. However, to solve a limited set of problems, it’s useful to use both traversal and URL dispatch together within the same application. Pyramid makes this possible via hybrid applications.
latex-warning.png
Reasoning about the behavior of a “hybrid” URL dispatch + traversal application can be challenging. To successfully reason about using URL dispatch and traversal together, you need to understand URL pattern matching, root factories, and the traversal algorithm, and the potential interactions between them. Therefore, we don’t recommend creating an application that relies on hybrid behavior unless you must.
28.1 A Review of Non-Hybrid Applications
When used according to the tutorials in its documentation Pyramid is a “dual-mode” framework: the tutorials explain how to create an application in terms of using either url dispatch or traversal. This chapter details how you might combine these two dispatch mechanisms, but we’ll review how they work in isolation before trying to combine them.
305
28. COMBINING TRAVERSAL AND URL DISPATCH
28.1.1 URL Dispatch Only
An application that uses url dispatch exclusively to map URLs to code will often have statements like this within application startup configuration:
1 # config is an instance of pyramid.config.Configurator
2
3 config.add_route(’foobar’, ’{foo}/{bar}’) 4 config.add_route(’bazbuz’, ’{baz}/{buz}’)
5
6 config.add_view(’myproject.views.foobar’, route_name=’foobar’) 7 config.add_view(’myproject.views.bazbuz’, route_name=’bazbuz’)
Each route corresponds to one or more view callables. Each view callable is associated with a route by passing a route_name parameter that matches its name during a call to add_view(). When a route is matched during a request, view lookup is used to match the request to its associated view callable. The presence of calls to add_route() signify that an application is using URL dispatch.
28.1.2 Traversal Only
An application that uses only traversal will have view configuration declarations that look like this:
1# config is an instance of pyramid.config.Configurator
2
3config.add_view(’mypackage.views.foobar’, name=’foobar’)
4config.add_view(’mypackage.views.bazbuz’, name=’bazbuz’)
When the above configuration is applied to an application, the mypackage.views.foobar view callable above will be called when the URL /foobar is visited. Likewise, the view mypackage.views.bazbuz will be called when the URL /bazbuz is visited.
Typically, an application that uses traversal exclusively won’t perform any calls to pyramid.config.Configurator.add_route() in its startup code.
306