WebStack

Annotated examples/Common/Login/__init__.py

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