__all__ = [] class AuthenticationRequired(Exception): """ Internal Exception class that is thrown inside L{AuthenticationMiddleware}, but not visible to other code. """ class ProtocolViolation(AuthenticationRequired): pass class AuthenticationMiddleware: """Base class for HTTP authorization schemes. @cvar authorization_required: the implemented Authorization method. It will be verified against Authorization headers. Subclasses must define this attribute. @type authorization_required: str """ authorization_method = None def __init__(self, app): """ @param app: is a WSGI application. """ assert self.authorization_method is not None self.app = app def authenticate(self, auth, environ, start_response): """ @type auth: str @param auth: is the part of the Authorization header after the method """ raise NotImplementedError def __call__(self, environ, start_response): assert isinstance(environ, dict) try: try: auth = environ["HTTP_AUTHORIZATION"] except KeyError: raise AuthenticationRequired("no Authorization header found") try: method, rest = auth.split(' ', 1) except ValueError: method, rest = auth, "" if method.lower() != self.authorization_method: raise AuthenticationRequired( "authorization method not implemented: %r" % method) return self.authenticate(rest, environ, start_response) except AuthenticationRequired, exc: return self.authorization_required(environ, start_response, exc) def www_authenticate(self, exception): """Generates a WWW-Authenticate header. Subclasses must implement this method. @type exception: AuthenticationRequired @param exception: reason for generating the header @rtype: (str, str) @returns: the header as (part_before_colon, part_after_colon) """ raise NotImplementedError def authorization_required(self, environ, start_response, exception): """Generate an error page after failed authentication. Apart from the exception parameter, this method behaves like a WSGI application. @type exception: AuthenticationRequired @param exception: reason for the authentication failure """ status = "401 Authorization required" html = "401 Authorization required" \ "

401 Authorization required

" headers = [("Content-Type", "text/html"), self.www_authenticate(exception), ("Content-Length", str(len(html)))] start_response(status, headers) if environ["REQUEST_METHOD"].upper() == "HEAD": return [] return [html]