6.1.2.3 Authentication
The publisher handler provides simple ways to control access to
modules and functions.
 
At every traversal step, the Publisher handler checks for presence of
__auth__ and __access__ attributes (in this order), as
well as __auth_realm__ attribute.
 
If __auth__ is found and it is callable, it will be called
with three arguments: the Request object, a string containing
the user name and a string containing the password. If the return
value of
__auth__ is false, then HTTP_UNAUTHORIZED is
returned to the client (which will usually cause a password dialog box
to appear).
 
If __auth__ is a dictionary, then the user name will be
matched against the key and the password against the value associated
with this key. If the key and password do not match,
HTTP_UNAUTHORIZED is returned. Note that this requires
storing passwords as clear text in source code, which is not very secure.
 
__auth__ can also be a constant. In this case, if it is false
(i.e. None, 0, "", etc.), then
HTTP_UNAUTHORIZED is returned.
 
If there exists an __auth_realm__ string, it will be sent
to the client as Authorization Realm (this is the text that usually
appears at the top of the password dialog box).
 
If __access__ is found and it is callable, it will be called
with two arguments: the Request object and a string containing
the user name. If the return value of __access__ is false, then
HTTP_FORBIDDEN is returned to the client.
 
If __access__ is a list, then the user name will be matched
against the list elements. If the user name is not in the list,
HTTP_FORBIDDEN is returned.
 
Similarly to __auth__, __access__ can be a constant.
 
In the example below, only user "eggs" with password "spam"can access the hello function:
 
 
  __auth_realm__ = "Members only"
  def __auth__(req, user, passwd):
  if user == "eggs" and passwd == "spam" or \
  user == "joe" and passwd == "eoj":
  return 1
  else:
  return 0
  def __access__(req, user):
  if user == "eggs":
  return 1
  else:
  return 0
  def hello(req):
  return "hello"
  
Here is the same functionality, but using an alternative technique:
 
 
  __auth_realm__ = "Members only"
  __auth__ = {"eggs":"spam", "joe":"eoj"}
  __access__ = ["eggs"]
  def hello(req):
  return "hello"
 
Since functions cannot be assigned attributes, to protect a function,
an __auth__ or __access__ function can be defined within
the function, e.g.:
 
 
  def sensitive(req):
  def __auth__(req, user, password):
  if user == 'spam' and password == 'eggs':
  # let them in
  return 1
  else:
  # no access
  return 0
  # something involving sensitive information
  return 'sensitive information`
  
Note that this technique will also work if __auth__ or
__access__ is a constant, but will not work is they are
a dictionary or a list.
 
The __auth__ and __access__ mechanisms exist
independently of the standard
PythonAuthenHandler. It
is possible to use, for example, the handler to authenticate, then the
__access__ list to verify that the authenticated user is
allowed to a particular function.
 
 Note:
In order for mod_python to access  __auth__,
the module containing it must first be imported. Therefore, any
module-level code will get executed during the import even if
 __auth__ is false.  To truly protect a module from
being accessed, use other authentication mechanisms, e.g. the Apache
 mod_auth or with a mod_python  PythonAuthenHandler handler.
  
  |