Opened 14 years ago

Closed 10 years ago

#393 enhancement closed duplicate (duplicate)

[PATCH] HTTP Basic Auth based guard

Reported by: itamarst Owned by:
Priority: normal Milestone:
Component: web Keywords:
Cc: Glyph, spiv, itamarst, dp, jknight Branch:
Author:

Description


Change History (5)

comment:1 Changed 14 years ago by itamarst

The following code doesn't do sessions, but really you could build sessions on
top of basic auth. Also it probably ought to have a logout method. But it works.
---------------


from twisted.web import resource, server
from twisted.cred.credentials import UsernamePassword, Anonymous,
IUsernamePassword, IUsernameHashedPassword
from twisted.cred.error import LoginFailed, UnauthorizedLogin


class BasicAuthWrapper(resource.Resource):
    """Wrap resource with HTTP Basic Auth based login."""
    
    isLeaf = True
    
    def __init__(self, portal, httpRealm="Twisted"):
        resource.Resource.__init__(self)
        self.portal = portal
        self.httpRealm = httpRealm

    def render(self, request):
        username, password = request.getUser(), request.getPassword()
        if not username:
            creds = Anonymous()
        else:
            creds = UsernamePassword(username, password)
        d = self.portal.login(creds, None, resource.IResource)
        d.addCallback(self._cbLoggedIn, request).addErrback(self._ebLoginFailed,
request)
        return server.NOT_DONE_YET

    def _cbLoggedIn(self, (interface, avatar, logout), request):
        # the session lasts one request - maybe someday we can implement sessions
        # on top of this.
        request.notifyFinish().addCallback(lambda r: logout())
        result = resource.getChildForRequest(avatar, request).render(request)
        if result != server.NOT_DONE_YET:
            request.write(result)
            request.finish()
    
    def _ebLoginFailed(self, f, request):
        f.trap(LoginFailed, UnauthorizedLogin)
        request.setResponseCode(401)
        request.setHeader("www-authenticate", 'Basic realm="%s"' % self.httpRealm)
        request.finish()

comment:2 Changed 14 years ago by Moshe Zadka

here's my own take on this:

from twisted.web import resource, server
from twisted.cred import credentials, error

class BasicAuthResource:
    
    __implements__ = resource.IResource
    isLeaf = True
    httpRealm="Twisted"

    def __init__(self, portal):
        self.portal = portal

    def render(self, request):
        username, password = request.getUser(), request.getPassword()
        if not username:
            creds = credentials.Anonymous()
        else:
            creds = credentials.UsernamePassword(username, password)
        d = self.portal.login(creds, None, resource.IResource)
        def cb((_, r, logout)):
            request.notifyFinished.addBoth(lambda _: logout())
            result = resource.getChildForRequest(r, request).render(request)
            if result != server.NOT_DONE_YET:
                request.write(result)
                request.finish()
        def eb(_):
            f.trap(LoginFailed, UnauthorizedLogin)
            request.setResponseCode(401)
            request.setHeader("www-authenticate",
                              'Basic realm="%s"' % self.httpRealm)
            request.finish()
        d.addCallbacks(callback=cb,errback=eb)
        d.addErrback(log.err)
        return server.NOT_DONE_YET

comment:3 Changed 14 years ago by Glyph

There is already code to do this in Nevow.  We need to get it merged at some point.

comment:4 Changed 10 years ago by Jean-Paul Calderone

Resolution: duplicate
Status: newclosed

#696 was a duplicate of this. There's a bunch more stuff there, so closing this one.

comment:5 Changed 7 years ago by <automation>

Owner: jknight deleted
Note: See TracTickets for help on using tickets.