1.1 --- a/WebStack/Resources/Login.py Sun Nov 12 02:52:38 2006 +0000
1.2 +++ b/WebStack/Resources/Login.py Sun Nov 12 02:54:02 2006 +0000
1.3 @@ -51,48 +51,18 @@
1.4
1.5 "Respond using the transaction 'trans'."
1.6
1.7 - fields_path = trans.get_fields_from_path(self.urlencoding)
1.8 - fields_body = trans.get_fields_from_body(self.encoding)
1.9 -
1.10 - # NOTE: Handle missing redirects better.
1.11 -
1.12 - if fields_body.has_key("app"):
1.13 - apps = fields_body["app"]
1.14 - app = apps[0]
1.15 - elif fields_path.has_key("app"):
1.16 - apps = fields_path["app"]
1.17 - app = apps[0]
1.18 - else:
1.19 - app = u""
1.20 -
1.21 - if fields_body.has_key("path"):
1.22 - paths = fields_body["path"]
1.23 - path = paths[0]
1.24 - elif fields_path.has_key("path"):
1.25 - paths = fields_path["path"]
1.26 - path = paths[0]
1.27 - else:
1.28 - path = u""
1.29 -
1.30 - if fields_body.has_key("qs"):
1.31 - qss = fields_body["qs"]
1.32 - qs = qss[0]
1.33 - elif fields_path.has_key("qs"):
1.34 - qss = fields_path["qs"]
1.35 - qs = qss[0]
1.36 - else:
1.37 - qs = u""
1.38 + app, path, qs = get_target(trans, self.urlencoding, self.encoding)
1.39
1.40 # Check for a submitted login form.
1.41
1.42 if fields_body.has_key("login"):
1.43 - if self.authenticator.authenticate(trans):
1.44 + if self.authenticator.authenticate(trans, fields_body.get("username"), fields_body.get("password")):
1.45 self._redirect(trans, app, path, qs)
1.46 # The above method does not return.
1.47
1.48 # Otherwise, show the login form.
1.49
1.50 - self._show_login(trans, app, path, qs)
1.51 + self.show_login(trans, app, path, qs)
1.52
1.53 def _redirect(self, trans, app, path, qs):
1.54
1.55 @@ -103,13 +73,13 @@
1.56
1.57 # Show the success page anyway.
1.58
1.59 - self._show_success(trans, app, path, qs)
1.60 + self.show_success(trans, app, path, qs)
1.61 if self.use_redirect:
1.62 trans.redirect(app + trans.encode_path(path, self.urlencoding) + qs)
1.63 else:
1.64 raise WebStack.Generic.EndOfResponse
1.65
1.66 - def _show_login(self, trans, app, path, qs):
1.67 + def show_login(self, trans, app, path, qs):
1.68
1.69 """
1.70 Writes a login screen using the transaction 'trans', including details of the
1.71 @@ -137,7 +107,7 @@
1.72 </html>
1.73 """ % (app, path, qs))
1.74
1.75 - def _show_success(self, trans, app, path, qs):
1.76 + def show_success(self, trans, app, path, qs):
1.77
1.78 # When authentication fails or is yet to take place, show the login
1.79 # screen.
1.80 @@ -172,33 +142,26 @@
1.81 self.credentials = credentials
1.82 self.cookie_name = cookie_name or "LoginAuthenticator"
1.83
1.84 - def authenticate(self, trans):
1.85 + def authenticate(self, trans, username, password):
1.86
1.87 """
1.88 Authenticate the sender of the transaction 'trans', returning 1 (true) if they are
1.89 - recognised, 0 (false) otherwise.
1.90 + recognised, 0 (false) otherwise. Use the 'username' and 'password' supplied as
1.91 + credentials.
1.92 """
1.93
1.94 # Process any supplied parameters.
1.95
1.96 fields = trans.get_fields_from_body()
1.97
1.98 - if fields.has_key("username") and fields.has_key("password"):
1.99 - usernames, passwords = fields["username"], fields["password"]
1.100 + # Check against the class's credentials.
1.101
1.102 - # Insist on only one username and password.
1.103 -
1.104 - if len(usernames) == 1 and len(passwords) == 1:
1.105 - username, password = usernames[0], passwords[0]
1.106 + if (username, password) in self.credentials:
1.107
1.108 - # Check against the class's credentials.
1.109 -
1.110 - if (username, password) in self.credentials:
1.111 + # Make a special cookie token.
1.112
1.113 - # Make a special cookie token.
1.114 -
1.115 - self.set_token(trans, username)
1.116 - return 1
1.117 + self.set_token(trans, username)
1.118 + return 1
1.119
1.120 return 0
1.121
1.122 @@ -212,4 +175,47 @@
1.123 path="/"
1.124 )
1.125
1.126 +# General functions.
1.127 +
1.128 +def get_target(trans, urlencoding, encoding):
1.129 +
1.130 + """
1.131 + Return the application, path and query string for 'trans' using the given
1.132 + 'urlencoding' (or path encoding) and request body 'encoding'.
1.133 + """
1.134 +
1.135 + fields_path = trans.get_fields_from_path(urlencoding)
1.136 + fields_body = trans.get_fields_from_body(encoding)
1.137 +
1.138 + # NOTE: Handle missing redirects better.
1.139 +
1.140 + if fields_body.has_key("app"):
1.141 + apps = fields_body["app"]
1.142 + app = apps[0]
1.143 + elif fields_path.has_key("app"):
1.144 + apps = fields_path["app"]
1.145 + app = apps[0]
1.146 + else:
1.147 + app = u""
1.148 +
1.149 + if fields_body.has_key("path"):
1.150 + paths = fields_body["path"]
1.151 + path = paths[0]
1.152 + elif fields_path.has_key("path"):
1.153 + paths = fields_path["path"]
1.154 + path = paths[0]
1.155 + else:
1.156 + path = u""
1.157 +
1.158 + if fields_body.has_key("qs"):
1.159 + qss = fields_body["qs"]
1.160 + qs = qss[0]
1.161 + elif fields_path.has_key("qs"):
1.162 + qss = fields_path["qs"]
1.163 + qs = qss[0]
1.164 + else:
1.165 + qs = u""
1.166 +
1.167 + return app, path, qs
1.168 +
1.169 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/WebStack/Resources/LoginRedirect.py Sun Nov 12 02:52:38 2006 +0000
2.2 +++ b/WebStack/Resources/LoginRedirect.py Sun Nov 12 02:54:02 2006 +0000
2.3 @@ -4,7 +4,7 @@
2.4 Login redirection resources, sending unauthenticated users to a login screen
2.5 URL.
2.6
2.7 -Copyright (C) 2004, 2005 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2004, 2005, 2006 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This library is free software; you can redistribute it and/or
2.11 modify it under the terms of the GNU Lesser General Public
2.12 @@ -30,14 +30,20 @@
2.13
2.14 encoding = "utf-8"
2.15
2.16 - def __init__(self, login_url, app_url, resource, authenticator, anonymous_parameter_name=None,
2.17 - anonymous_username="anonymous", logout_parameter_name=None, logout_url="/",
2.18 - use_logout_redirect=1, urlencoding=None):
2.19 + def __init__(self, resource, authenticator, login_url=None, app_url=None,
2.20 + anonymous_parameter_name=None, anonymous_username="anonymous",
2.21 + logout_parameter_name=None, logout_url="/", use_logout_redirect=1,
2.22 + urlencoding=None):
2.23
2.24 """
2.25 - Initialise the resource with a 'login_url', an 'app_url' where the
2.26 - 'resource' for the application being protected should be reachable, and
2.27 - an 'authenticator'.
2.28 + Initialise the resource with a 'resource' for the application being
2.29 + protected and an 'authenticator' protecting the resource.
2.30 +
2.31 + If the optional 'login_url' and 'app_url' are provided, these values
2.32 + will be used to locate the login application and protected application
2.33 + respectively. Such values, if not provided, must be otherwise set at a
2.34 + later time or provided by 'get_login_url' and 'get_app_url' methods in
2.35 + a subclass of this class.
2.36
2.37 If the optional 'anonymous_parameter_name' is set, clients providing a
2.38 parameter of that name in the URL will not be authenticated, but then
2.39 @@ -117,12 +123,18 @@
2.40 if qs:
2.41 qs = "?" + qs
2.42 trans.redirect("%s?app=%s&path=%s&qs=%s" % (
2.43 - self.login_url,
2.44 - trans.encode_path(self.app_url, self.urlencoding),
2.45 + self.get_login_url(trans),
2.46 + trans.encode_path(self.get_app_url(trans), self.urlencoding),
2.47 trans.encode_path(path, self.urlencoding),
2.48 trans.encode_path(qs, self.urlencoding))
2.49 )
2.50
2.51 + def get_app_url(self, trans):
2.52 + return self.app_url
2.53 +
2.54 + def get_login_url(self, trans):
2.55 + return self.login_url
2.56 +
2.57 def _show_logout(self, trans, redirect):
2.58
2.59 """