posted on: 2009-10-27 18:48:38
I took the cherrypy wsgi server and setup a basic and digest authentication scheme. Works great.
>This is a very basic setup and I doubt it is much different then the one that comes with python. I start with cherrypy wsgi server, not the whole server. Then I parse the wsgi environ and perform http authentication.
Here is the code
#!/usr/bin/env python """ This file is minimal techniques to get both types of athentication through a simple wsgi server mos likely this should be delegated to classes, but I have not done that since all I wanted to make is a simple example, that uses both types of authentication. I started with the example in CherryPy WSGI stand alone server. """ import CherryPyWSGI as cwsgi import base64 from hashlib import md5 def my_crazy_app(environ, start_response): """Root directory no authenticaion""" status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello world!\n'] def my_basic_app(environ, start_response): """This basic authenticated file""" status = '200 OK' response_headers = [('Content-type','text/html')] start_response(status, response_headers) return ['<html><body><p>This is there the webpages go</p></body></html>'] def authenticate_basic_app(environ,start_response): """Performs the authentcation""" auth_response = environ.get("HTTP_AUTHORIZATION","none:none") name,passwd = getBasicCredentials(auth_response) if passwd==getBasicPassword(name): ret_value = my_basic_app(environ,start_response) print passwd, getBasicPassword(name) else: print passwd, getBasicPassword(name) ret_value = basicAuthenticationFailed(environ,start_response) return ret_value def getBasicCredentials(both): """Parses the HTTP_AUTHORIZATION item for basic credentials""" encd = both.split()[-1] values = base64.b64decode(encd).split(':') if len(values)==2: return values[0],values[1] return "none","none" def getBasicPassword(user): """Dummy function for getting a pasword""" return "dogs" def basicAuthenticationFailed(environ,start_response): """Failed authentication""" status = '401 Unauthorized' response_headers = [('WWW-Authenticate','basic realm="Secure Area"'),('Content-type','text/html')] start_response(status,response_headers) return ["<html><body>Authorization has failed</body></html>"] def authenticate_digest_app(environ,start_response): """This begins the digest authentication process""" auth_response = environ.get("HTTP_AUTHORIZATION","none") data = getDigestCredentials(auth_response) data['method'] = environ.get('REQUEST_METHOD') if getDigestResponse(data): ret_value = my_digest_app(environ,start_response) else: ret_value = digestAuthenticationFailed(environ,start_response) return ret_value def getDigestCredentials(auth_response): """Parses the return values from 'HTTP_AUHORIZATION' string""" data = {} for item in auth_response.split(','): part = item.find("=") if part>0: data[item[:part].strip()] = item[part+1:].strip("\"") return data def getDigestResponse(data): """Creates the hash values that are returned""" #first section could probably be stored in a data base user = data.get("Digest username") realm = data.get("realm") valueA = md5() valueA.update('%s:%s:%s' % (user, realm, 'secret')) hashA = valueA.hexdigest() #this section will change on request nonce = data.get("nonce") uri = data.get("uri") method = data.get('method') valueB = md5() valueB.update("%s:%s"%(method,uri)) hashB = valueB.hexdigest() value = md5() value.update("%s:%s:%s"%(hashA,nonce,hashB)) return data.get("response")==value.hexdigest() def digestAuthenticationFailed(environ,start_response): """Failed digest request""" status = '401 Unauthorized' response_headers = [('WWW-Authenticate','Digest realm="Secure Area" nonce="two"'),('Content-type','text/html')] start_response(status,response_headers) return ["<html><body>Authorization has failed</body></html>"] def my_digest_app(environ, start_response): """Success""" status = '200 OK' response_headers = [('Content-type','text/html')] start_response(status, response_headers) return ['<html><body><p>Yo Yo, digest stylie.</p></body></html>'] """ Creates a cherrypy wsgi server with three different locations, / ... no authentication /basic... basic authentication /digest ... digest authentication """ d = cwsgi.WSGIPathInfoDispatcher({'/': my_crazy_app, '/basic': authenticate_basic_app, '/digest':authenticate_digest_app}) server = cwsgi.CherryPyWSGIServer(('0.0.0.0', 8080), d) if __name__ == '__main__': try: server.start() except KeyboardInterrupt: server.stop()
I got the http info from wikapedia, here
and I found some other info that I might add when I find it again.
Comments
create comment?