Hello,
I'm writing a web application/service using the RESTful
design
pattern. The app is a sheep breed society database. I'm
having a
problem with digest authentication using the method Robert
Brewer
suggested recently for contioional authorisation.
What I'm trying to acheive is as follows: anyone can go to
the domain
root and will get a web page offering them the choice of
either
logging in, or going to one of the resources (sheep data)
which
requires no authentication for GET verbs but does require
authentication for PUT, POST and DELETE. Every resource
apart from
this resource and the home page require authentication.
The directory structure is:
root
/login
/sheep
/data
/more resources....
/members
/member resources...
and so on. The root resource only supports GET and requires
no
authentication. /login is the resource users are linked to
when they
click the login link - they then get the browser
authentication dialog
and on completing that get a page with links to all the
other
resources. The /sheep/data resource should require no
authentication
for GET, but should require authentication for PUT, POST and
DELETE.
Using the web pages a user is either authenticated before
they get to
the /sheep/data resource, in which case they can make
requests with
all the verbs with no problem, or they get unauthenticated
access to
GET. Both these cases work fine. However when I tested the
case of an
unauthenticated POST to /sheep/data I first get the password
dialog,
and on entering the proper credentials, instead of running
the POST
method I get a 405 method not supported.
I put a few print statements into the cherrypy files, and
after
working back I found that the method passed to Request.run
in
_cprequest has the body of the POST request prepended to the
POST
methodname, so Resource.run sees something like
'SearchArg=&Search=SearchPOST', which of course leads
direct to a
405. The first POST that triggers the 401 is fine.
The really wierd thing is that sometimes, for no reason I've
been able
to identify the POST request wil run OK the first time I try
it after
restarting muy app and the browser. Also the stuff prepended
to POST
differs according to the browser - I use Firefox mostly, but
with IE7
less of the body gets prepended, and with Opera nothing gets
prepended
by eventually cherrypy crashes with a socket timeout. I've
looked at
the headers sent by firefox (with LiveHTTPheaders) and they
look OK.
I've tried thos both on a Windows XP machine and a Ubuntu
machine with
exactly the same result.
I'm a bit stuck, since my knowledge of python and the http
libraries
is not enough to enable me to work out where in the server
(or whether
in the server) the HTTP method is getting corrupted. I can't
find the
call to resource.run - probably because it's an indirect
call and I
can't work out where it might be called from.
If it were C I'd be looking for a buffer overflow and I'd
know how to
find it - but that's not supposed to happen in python - is
it?.
The relevant bit of my __init__.py, where the config is set
up is (I
know it's not very tidy, but I'm at the 'suck it and see'
stage with
cherrypy so bits have ben hacked in and out):
def conditional_digest_auth(verbs=['POST', 'PUT',
'DELETE']):
"""Turn on Digest auth based on various
criteria."""
if cherrypy.request.method in verbs:
cherrypy.tools.digest_auth._setup()
def get_users():
return {'test' : 'test#'}
def StartApp(appconf, cp_conf, startfile):
global dbConn
_copyconf(appconf, startfile)
# Get a connection to the database - shared between
cherrypy
threads
dbConn =
psycopg2.connect(host='localhost',user='postgres',
password='exp<35get', database='sss_test')
# Now load our modules
import approot
import sheep
import flock
import test
# Configure CherryPy
current_dir =
os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update(cp_conf)
cherrypy.tools.conditional_digest_auth =
cherrypy.Tool('on_start_resource', conditional_digest_auth)
# Create and mount the tree
db = approot.Root()
db.login = approot.Login()
db.sheep = sheep.Sheep()
db.sheep.data = sheep.Data()
db.flock = flock.Flock()
db.sheep.test = test.Test()
conf = {'/': {'request.dispatch':
cherrypy.dispatch.MethodDispatcher(),
'tools.staticdir.root':current_dir}
,'/files': {'tools.staticdir.on':True,
'tools.staticdir.dir':'static'}
,'/login' : {'tools.digest_auth.on':True,
'tools.digest_auth.realm':'SSS
Database',
'tools.digest_auth.users':
get_users}
,'/sheep' : {'tools.digest_auth.on':True,
'tools.digest_auth.realm':'SSS
Database',
'tools.digest_auth.users':
get_users}
,'/sheep/data' : {'tools.digest_auth.on' :
False,
'tools.conditional_digest_auth.on':
True,
'tools.conditional_digest_auth.verbs':
['POST'],
'tools.digest_auth.realm':
'SSS
Database',
'tools.digest_auth.users':
get_users }
}
cherrypy.tree.mount(db, "/", conf)
# Start CherryPy
cherrypy.server.quickstart()
cherrypy.engine.start()
If I remove all the auth configuration except the
conditional stuff
on /sheep/data I get exactly the same results.
Any ideas, or help as to where I look in the server code,
gratefully
received.
Thanks
Pete H
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the
Google Groups "cherrypy-users" group.
To post to this group, send email to cherrypy-users googlegroups.com
To unsubscribe from this group, send email to
cherrypy-users-unsubscribe googlegroups.com
For more options, visit this group at h
ttp://groups.google.com/group/cherrypy-users?hl=en
-~----------~----~----~----~------~----~------~--~---
|