Q:

Stuck with Python HTTP Server with Basic Authentication using BaseHTTP

I am stuck trying to get a python based webserver to work.
I want to do Basic Authentication (sending a 401 header) and authenticating against a list of users. I have no trouble sending the 401 response with "WWW-Authorize" header, I can validate the users response (base64 encoded username & password), however, the login box keeps popping up after successful validation.
import SimpleHTTPServer
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class Handler(BaseHTTPRequestHandler):
    ''' Main class to present webpages and authentication. '''
    def do_HEAD(self):
        print "send header"
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        ''' Present frontpage with user authentication. '''
        self.do_HEAD()

        if self.headers.getheader('Authorization') == None:
            self.wfile.write('no auth header received')
            pass
        elif self.headers.getheader('Authorization') == 'Basic dGVzdDp0ZXN0':
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('authenticated!')
            pass
        else:
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('not authenticated')
            pass

httpd = SocketServer.TCPServer(("", 10001), Handler)

httpd.serve_forever()

if __name__ == '__main__':
    main()

On first load (http://localhost:10001) the loginbox pops up, I enter test, test (the correct user) user is validated ok, but box pops back up, if I click cancel, I get to the validated page...
Can anyone lend a hand here? I suspect it has something to do with the fact that authorization happens under do_GET, which is triggered everytime a page loads.

A:

Try this for size:
import SimpleHTTPServer
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class Handler(BaseHTTPRequestHandler):
    ''' Main class to present webpages and authentication. '''
    def do_HEAD(self):
        print "send header"
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_AUTHHEAD(self):
        print "send header"
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        ''' Present frontpage with user authentication. '''
        if self.headers.getheader('Authorization') == None:
            self.do_AUTHHEAD()
            self.wfile.write('no auth header received')
            pass
        elif self.headers.getheader('Authorization') == 'Basic dGVzdDp0ZXN0':
            self.do_HEAD()
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('authenticated!')
            pass
        else:
            self.do_AUTHHEAD()
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('not authenticated')
            pass

httpd = SocketServer.TCPServer(("", 10001), Handler)

httpd.serve_forever()

if __name__ == '__main__':
    main()

A:

That's because you are unconditionally sending 401 and WWW-Authenticate header in response. You only need to do this when there are no acceptable authentication credentials in request. If you are satisfied with request, send 200 (or whatever appropriate) and do not request authentication again.

