Graham Dumpleton
grahamd at dscpl.com.au
Fri Feb 17 00:14:43 EST 2006
Deron Meranda wrote .. > Implementing HTTP BASIC is actually pretty straight forward. > Read http://www.faqs.org/rfcs/rfc2617.html -- you can ignore > all the Proxy stuff if you're not trying to write a proxy server. > The general strategy is to look for the "Authorization" > input header. If it's there, decode it (check that the scheme > is "BASIC" (case-insensitive) then base64-decode the > username:password). Then validate the username and password > by whatever means you want. > > If there is no Authorization header, or it is not valid, then you > need to return an HTTP 401; and also insure you also output > an WWW-Authenticate response header. Code for basic authentication included down below as drawn from my own library of play stuff. Haven't had a chance to put something together to properly show how to use it in original posters example, but can be adapted by simply creating instance of BasicAuthentication class with appropriate parameters and then using instance as callable object. realm = "Disney Land" userdb = { "mickey": "mouse" } authenticator = BasicAuthentication(realm,userdb) authenticator(req) if req.user: # was able to autheticate okay .... Code for BasicAuthentication is then as follows. I hope it still runs, I have not used/tested this in a while. class BasicAuthentication: def __init__(self,realm,auth,access=None): self.__realm = realm self.__auth = auth self.__access = access def __call__(self,req): user = None passwd = None if req.headers_in.has_key('Authorization'): try: header = req.headers_in['Authorization'] scheme,credentials = header.split(None,1) credentials = credentials.strip() scheme = scheme.lower() if scheme == 'basic': credentials = base64.decodestring(credentials) user,passwd = string.split(credentials,':',1) else: raise apache.SERVER_RETURN, apache.HTTP_BAD_REQUEST except: raise apache.SERVER_RETURN, apache.HTTP_BAD_REQUEST if self.__realm is None: raise apache.SERVER_RETURN, apache.HTTP_INTERNAL_SERVER_ERROR if not user: s = 'Basic realm="%s"' % self.__realm req.err_headers_out['WWW-Authenticate'] = s raise apache.SERVER_RETURN, apache.HTTP_UNAUTHORIZED if callable(self.__auth): result = self.__auth(req,user,passwd) else: if type(self.__auth) is types.DictionaryType: result = self.__auth.has_key(user) and \ self.__auth[user] == passwd else: result = self.__auth if not result: s = 'Basic realm="%s"' % self.__realm req.err_headers_out['WWW-Authenticate'] = s raise apache.SERVER_RETURN, apache.HTTP_UNAUTHORIZED if self.__access is not None: if callable(self.__access): result = self.__access(req,user) else: if type(self.__access) in (types.ListType,types.TupleType): result = user in self.__access else: result = self.__access # If access check failed, and authentication was # performed with actual user details being # checked, as opposed to any user being allowed, # must provide ability to reauthenticate with a # different user and not just return forbidden. if not result: if self.__auth is not None and (callable(self.__auth) or \ type(self.__auth) == types.DictionaryType): s = 'Basic realm="%s"' % self.__realm req.err_headers_out['WWW-Authenticate'] = s raise apache.SERVER_RETURN, apache.HTTP_UNAUTHORIZED else: raise apache.SERVER_RETURN, apache.HTTP_FORBIDDEN req.user = user
|