WebStack

examples/Common/Login/__init__.py

135:ecc6825a869f
2004-05-29 paulb [project @ 2004-05-29 21:08:48 by paulb] Fixed the content type for the login screen. Added decoding of encoded redirect URL information.
     1 #!/usr/bin/env python     2      3 "An example login screen."     4      5 import WebStack.Generic     6 import md5     7      8 class LoginResource:     9     10     "A resource providing a login screen."    11     12     def __init__(self, authenticator):    13     14         "Initialise the resource with an 'authenticator'."    15     16         self.authenticator = authenticator    17     18     def respond(self, trans):    19     20         fields = trans.get_fields_from_body()    21         redirect = ""    22     23         if fields.has_key("redirect"):    24             redirects = fields["redirect"]    25             redirect = redirects[0]    26             if self.authenticator.authenticate(trans):    27                 trans.set_header_value("Location", redirect)    28                 trans.set_response_code(307)    29                 return    30         else:    31             fields = trans.get_fields_from_path()    32             if fields.has_key("redirect"):    33                 redirects = fields["redirect"]    34                 redirect = redirects[0]    35     36         # When authentication fails or is yet to take place, show the login    37         # screen.    38     39         trans.set_content_type(WebStack.Generic.ContentType("text/html"))    40         out = trans.get_response_stream()    41         out.write("""    42 <html>    43   <head>    44     <title>Login Example</title>    45   </head>    46   <body>    47     <h1>Login</h1>    48     <form method="POST">    49       <p>Username: <input name="username" type="text" size="12"/></p>    50       <p>Password: <input name="password" type="text" size="12"/></p>    51       <p><input name="login" type="submit" value="Login"/></p>    52       <input name="redirect" type="hidden" value="%s"/>    53     </form>    54   </body>    55 </html>    56 """ % redirect)    57     58     def _decode(self, url):    59     60         "Decode the given 'url' for redirection purposes."    61     62         return url.replace("%3f", "?").replace("%26", "&")    63     64 class LoginAuthenticator:    65     66     def __init__(self, secret_key, credentials, cookie_name=None):    67     68         """    69         Initialise the authenticator with a 'secret_key', the authenticator's registry of    70         'credentials' and an optional 'cookie_name'.    71     72         The 'credentials' must be an object which supports tests of the form    73         '(username, password) in credentials'.    74         """    75     76         self.secret_key = secret_key    77         self.credentials = credentials    78         self.cookie_name = cookie_name or "LoginAuthenticator"    79     80     def authenticate(self, trans):    81     82         # Process any supplied parameters.    83     84         fields = trans.get_fields_from_body()    85     86         if fields.has_key("username") and fields.has_key("password"):    87             usernames, passwords = fields["username"], fields["password"]    88     89             # Insist on only one username and password.    90     91             if len(usernames) == 1 and len(passwords) == 1:    92                 username, password = usernames[0], passwords[0]    93     94                 # Check against the class's credentials.    95     96                 if (username, password) in self.credentials:    97     98                     # Make a special cookie token.    99                     # NOTE: This should be moved into a common library.   100    101                     trans.set_cookie_value(   102                         self.cookie_name,   103                         username + ":" + md5.md5(username + self.secret_key).hexdigest()   104                     )   105    106                     return 1   107    108         return 0   109    110 # vim: tabstop=4 expandtab shiftwidth=4