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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
.. _api_narrative:
Using the :mod:`repoze.who` Application Programming Interface (API)
===================================================================
.. _without_middleware:
Using :mod:`repoze.who` without Middleware
------------------------------------------
An application which does not use the :mod:`repoze.who` middleware needs
to perform two separate tasks to use :mod:`repoze.who` machinery:
- At application startup, it must create an :class:`repoze.who.api:APIFactory`
instance, populating it with a request classifier, a challenge decider,
and a set of plugins. It can do this process imperatively
(see :ref:`imperative_configuration`), or using a declarative
configuration file (see :ref:`declarative_configuration`). For the latter
case, there is a convenience function,
:func:`repoze.who.config.make_api_factory_with_config`:
.. code-block:: python
# myapp/run.py
from repoze.who.config import make_api_factory_with_config
who_api_factory = None
def startup(global_conf):
global who_api_factory
who_api_factory = make_api_factory_with_config(global_conf,
'/path/to/who.config')
- When it needs to use the API, it must call the ``APIFactory``, passing
the WSGI environment to it. The ``APIFactory`` returns an object
implementing the :class:`repoze.who.interfaces:IRepozeWhoAPI` interface.
.. code-block:: python
# myapp/views.py
from myapp.run import who_api_factory
def my_view(context, request):
who_api = who_api_factory(request.environ)
- Calling the ``APIFactory`` multiple times within the same request is
allowed, and should be very cheap (the API object is cached in the
request environment).
.. _middleware_api_hybrid:
Mixed Use of :mod:`repoze.who` Middleware and API
-------------------------------------------------
An application which uses the :mod:`repoze.who` middleware may still need
to interact directly with the ``IRepozeWhoAPI`` object for some purposes.
In such cases, it should call :func:`repoze.who.api:get_api`, passing
the WSGI environment.
.. code-block:: python
from repoze.who.api import get_api
def my_view(context, request):
who_api = get_api(request.environ)
Alternately, the application might configure the ``APIFactory`` at startup,
as above, and then use it to find the API object, or create it if it was
not already created for the current request (e.g. perhaps by the middleware):
.. code-block:: python
def my_view(context, request):
who_api = context.who_api_factory(request.environ)
.. _writing_custom_login_view:
Writing a Custom Login View
---------------------------
:class:`repoze.who.api.API` provides a helper method to assist developers
who want to control the details of the login view. The following
BFG example illustrates how this API might be used:
.. code-block:: python
:linenos:
def login_view(context, request):
message = ''
who_api = get_api(request.environ)
if 'form.login' in request.POST:
creds = {}
creds['login'] = request.POST['login']
creds['password'] = request.POST['password']
authenticated, headers = who_api.login(creds)
if authenticated:
return HTTPFound(location='/', headers=headers)
message = 'Invalid login.'
else:
# Forcefully forget any existing credentials.
_, headers = who_api.login({})
request.response_headerlist = headers
if 'REMOTE_USER' in request.environ:
del request.environ['REMOTE_USER']
return {'message': message}
This application is written as a "hybrid": the :mod:`repoze.who` middleware
injects the API object into the WSGI enviornment on each request.
- In line 4, this application extracts the API object from the environ
using :func:`repoze.who.api:get_api`.
- Lines 6 - 8 fabricate a set of credentials, based on the values the
user entered in the form.
- In line 9, the application asks the API to authenticate those credentials,
returning an identity and a set of respones headers.
- Lines 10 and 11 handle the case of successful authentication: in this
case, the application redirects to the site root, setting the headers
returned by the API object, which will "remember" the user across requests.
- Line 13 is reached on failed login. In this case, the headers returned
in line 9 will be "forget" headers, clearing any existing cookies or other
tokens.
- Lines 14 - 16 perform a "fake" login, in order to get the "forget" headers.
- Line 18 sets the "forget" headers to clear any authenticated user for
subsequent requests.
- Lines 19 - 20 clear any authenticated user for the current request.
- Line 22 returns any message about a failed login to the rendering template.
.. _interfaces:
Interfaces
----------
.. automodule:: repoze.who.interfaces
.. autointerface:: IAPIFactory
:members:
.. autointerface:: IAPI
:members:
.. autointerface:: IPlugin
:members:
.. autointerface:: IRequestClassifier
:members:
.. autointerface:: IChallengeDecider
:members:
.. autointerface:: IIdentifier
:members:
.. autointerface:: IAuthenticator
:members:
.. autointerface:: IChallenger
:members:
.. autointerface:: IMetadataProvider
:members:
|