summaryrefslogtreecommitdiff
path: root/paste/auth/multi.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/auth/multi.py')
-rw-r--r--paste/auth/multi.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/paste/auth/multi.py b/paste/auth/multi.py
new file mode 100644
index 0000000..b378fa6
--- /dev/null
+++ b/paste/auth/multi.py
@@ -0,0 +1,79 @@
+# (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)
+