HTTP authentication is the standard way to authenticate access to
resources. It has a number of flaws, and it not the most common way
to do authentication on the web -- using standard forms is more
common. However, in some circumstances it is the only possible way --
in particular, using non-browser tools to access pages (like a DAV
client, an XML-RPC client, etc.)
HTTP authentication occurs when the server returns a 401 status (as in
``self.response().setStatus(401, 'Authorization Required')`` ) The
server also must set another header, ``WWW-Authenticate: Basic
realm="realm name"`` The realm name is the only message the
user will see explaining what they are logging into (though they
should know what page they are trying to access).
Clients will sent a header like Authorization: Basic xxx (where xxx is
the authorization information)
Clients generally do not send authentication information until they
are asked to do so (by receiving a 401 error). In typical usage, this
back and forth will occur for every page access. (Though I don't see
any reason you can't use the session and cookies like you would with
normal, form-based authentication).
There is another style of authentication (this style is termed
"Basic"), called "Digest" -- it sends a hash of the password, in a
challenge-response style. This is more secure, as you can't sniff
passwords. However, for reasons I cannot fathom, many major browsers
still do not support this kind of authentication. Instead, you
may use SSL to secure the password.
Setting up Apache
-----------------
Apache does not normally send the Authorization header onto clients.
To get around this you must use mod_rewrite (this is also typical with
Zope, but I haven't gotten their technique to work for me)
Put this rewrite rule in::
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule /WK(.*) /WK2$1?AUTH=%1 [QSA,L,PT]
``/WK2`` is the real location of the WebKit hander -- either a
location set up for mod_webkit, or another adapter. The
``RewriteCond`` line will capture the Authorization: header, which can
be referenced by %1. The ``RewriteRule`` line will add a variable
``AUTH`` to the query string.
(I'm not entirely sure about the security of this -- the
authentication information doesn't show up in the log, though)
In your servlet
---------------
In the servlet, you must both send the right information, and then
receive that authorization. To require authentication::
res = self.response()
res.setStatus(401, 'Authorization Required')
res.setHeader('WWW-Authenticate', 'Basic realm="%s"' % realm)
To process it::
import base64
def authorized(self):
req = self.request()
httpAuth = req.field('AUTH', None)
if not httpAuth: return 0
authType, auth = httpAuth.split(' ', 1)
assert authType.lower() == 'basic', 'Only basic HTTP authentication is supported'
name, password = base64.decodestring(auth.strip()).split(':', 1)
return self.authorizeUser(name, password)
(If you are using HTTPAdapter, you will receive the authentication
information in ``self.request().environ()['HTTP_AUTHORIZATION']`` )
-- IanBicking_ - 10 May 2002
Alternative Approach
--------------------
You can compile Apache 1.3 with SECURITY_HOLE_PASS_AUTHORIZATION_
which will cause apache to pass the HTTP_AUTHORIZATION environment
variable to your script. If you don't want to recompile apache, you
can use a much simpler mod_rewrite setup to add an additional
environment variable::
WKServer localhost 8086
SetHandler webkit-handler
RewriteEngine On
RewriteRule /WK(.*) - [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},PT]
.. _SECURITY_HOLE_PASS_AUTHORIZATION: http://httpd.apache.org/dev/apidoc/apidoc_SECURITY_HOLE_PASS_AUTHORIZATION.html
With this you scan check
``self.request().environ()['HTTP_AUTHORIZATION']`` and
``self.request().environ()['X-HTTP_AUTHORIZATION']`` to find
authorization Information.
There is also a patch to mod_webkit implementing passing of
Authorisation Info to the Application Server available at
http://blogs.23.nu/c0re/stories/1410/