80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
|
# (c) 2005 Clark C. Evans
|
||
|
# This module is part of the Python Paste Project and is released under
|
||
|
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||
|
# This code was written with funding by http://prometheusresearch.com
|
||
|
"""
|
||
|
Authentication via Multiple Methods
|
||
|
|
||
|
In some environments, the choice of authentication method to be used
|
||
|
depends upon the environment and is not "fixed". This middleware allows
|
||
|
N authentication methods to be registered along with a goodness function
|
||
|
which determines which method should be used. The following example
|
||
|
demonstrates how to use both form and digest authentication in a server
|
||
|
stack; by default it uses form-based authentication unless
|
||
|
``*authmeth=digest`` is specified as a query argument.
|
||
|
|
||
|
>>> from paste.auth import form, cookie, digest, multi
|
||
|
>>> from paste.wsgilib import dump_environ
|
||
|
>>> from paste.httpserver import serve
|
||
|
>>>
|
||
|
>>> multi = multi.MultiHandler(dump_environ)
|
||
|
>>> def authfunc(environ, realm, user):
|
||
|
... return digest.digest_password(realm, user, user)
|
||
|
>>> multi.add_method('digest', digest.middleware, "Test Realm", authfunc)
|
||
|
>>> multi.set_query_argument('digest')
|
||
|
>>>
|
||
|
>>> def authfunc(environ, username, password):
|
||
|
... return username == password
|
||
|
>>> multi.add_method('form', form.middleware, authfunc)
|
||
|
>>> multi.set_default('form')
|
||
|
>>> serve(cookie.middleware(multi))
|
||
|
serving on...
|
||
|
|
||
|
"""
|
||
|
|
||
|
class MultiHandler(object):
|
||
|
"""
|
||
|
Multiple Authentication Handler
|
||
|
|
||
|
This middleware provides two othogonal facilities:
|
||
|
|
||
|
- a manner to register any number of authentication middlewares
|
||
|
|
||
|
- a mechanism to register predicates which cause one of the
|
||
|
registered middlewares to be used depending upon the request
|
||
|
|
||
|
If none of the predicates returns True, then the application is
|
||
|
invoked directly without middleware
|
||
|
"""
|
||
|
def __init__(self, application):
|
||
|
self.application = application
|
||
|
self.default = application
|
||
|
self.binding = {}
|
||
|
self.predicate = []
|
||
|
def add_method(self, name, factory, *args, **kwargs):
|
||
|
self.binding[name] = factory(self.application, *args, **kwargs)
|
||
|
def add_predicate(self, name, checker):
|
||
|
self.predicate.append((checker, self.binding[name]))
|
||
|
def set_default(self, name):
|
||
|
""" set default authentication method """
|
||
|
self.default = self.binding[name]
|
||
|
def set_query_argument(self, name, key = '*authmeth', value = None):
|
||
|
""" choose authentication method based on a query argument """
|
||
|
lookfor = "%s=%s" % (key, value or name)
|
||
|
self.add_predicate(name,
|
||
|
lambda environ: lookfor in environ.get('QUERY_STRING',''))
|
||
|
def __call__(self, environ, start_response):
|
||
|
for (checker, binding) in self.predicate:
|
||
|
if checker(environ):
|
||
|
return binding(environ, start_response)
|
||
|
return self.default(environ, start_response)
|
||
|
|
||
|
middleware = MultiHandler
|
||
|
|
||
|
__all__ = ['MultiHandler']
|
||
|
|
||
|
if "__main__" == __name__:
|
||
|
import doctest
|
||
|
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
||
|
|