[Twisted-web] integration of HTTP Basic Auth and cred

Manlio Perillo manlio_perillo at libero.it
Sun Jun 4 06:21:20 CDT 2006


Hi.

I have written a small module for integrating HTTP Basic Auth and cred.
This is like guard.SessionWrapper.

I'm posting this module here because I'm not sure I'm doing the right thing.


Thanks and regards  Manlio Perillo
-------------- next part --------------
"""cred integration with HTTP Basic Authentication.
"""


from zope.interface import Interface, Attribute, implements

from twisted.web import http
from twisted.cred import portal
from twisted.cred.credentials import UsernamePassword, Anonymous
from twisted.cred.error import UnauthorizedLogin

from nevow import inevow, url, stan


class INamedRealm(portal.IRealm):
    # this is used in the HTTP WWW-Authenticate header
    name = Attribute("The name of the realm")


class Forbidden(object):
    implements(inevow.IResource)

    def locateChild(self, ctx, segments):
        return self

    def renderHTTP(self, ctx):
        request = inevow.IRequest(ctx)
        request.setResponseCode(http.FORBIDDEN)
        return ("<html><head><title>Forbidden</title></head>"
                "<body><h1>Forbidden</h1>Request was forbidden.</body></html>")


def nomind(*args): return None


class HTTPAuthWrapper(object):
    """Wrapper for HTTP Basic Authentication
    """

    implements(inevow.IResource)

    # The interface to cred for when logging into the portal
    credInterface = inevow.IResource
    resource = None
    
    def __init__(self, portal, mindFactory=None, credInterface=None):
        self.portal = portal
        
        if mindFactory is None:
            mindFactory = nomind
        self.mindFactory = mindFactory
        
        if credInterface is not None:
            self.credInterface = credInterface
        
    def renderHTTP(self, ctx):
        def _cb((iface, res, logout)):
            self.resource = inevow.IResource(res)
            
            req = inevow.IRequest(ctx)

            # XXX remove the Authorization header 
            # (compatibility with guard) 
            del req.getAllHeaders()["authorization"]

            return self.resource.renderHTTP(ctx)
        
        
        request = inevow.IRequest(ctx)
        realm = self.portal.realm
        
        username, password = request.getUser(), request.getPassword()
        
        # XXX TODO handle anonymous access?
        if (username, password) == ('', ''):
            request.setHeader('WWW-Authenticate', 
                              'Basic realm="%s"' % realm.name)
            request.setResponseCode(http.UNAUTHORIZED)
            
            # XXX
            return "Authentication required."
        else:
            credentials = UsernamePassword(username, password)
            mind = self.mindFactory(request, credentials)
            
            d = self.portal.login(credentials, mind,
                                  self.credInterface)
            d.addCallback(_cb)
            d.addErrback(self.incorrectLoginError, ctx)
            
            return d

    def locateChild(self, ctx, segments):
        # XXX not sure
        if not self.resource:
            if not segments:
                return self, ()
            elif not segments[0]:
                return self, ()
            else:
                return None, ()
        else:
            if not segments:
                return self.resource, ()
            elif not segments[0]:
                return self.resource, ()
            else:
                return self.resource.locateChild(ctx, segments)
  
    def incorrectLoginError(self, error, ctx):
        """Called on login failure.
        You can override this, as an example placing a limit on the
        number of failed logins.
        """
        
        request = inevow.IRequest(ctx)
        realm = self.portal.realm
        
        error.trap(UnauthorizedLogin)

        request.setHeader('WWW-Authenticate', 
                          'Basic realm="%s"' % realm.name)
        request.setResponseCode(http.UNAUTHORIZED)
        
        # XXX
        return "Authentication failed."


More information about the Twisted-web mailing list