I make apps for other people

Python decorators for handler access control

Posted by Chris Jones
On July 14th, 2011 at 17:05

Permalink | Trackback | Links In |

Comments Off on Python decorators for handler access control
Posted in General

Given that a REST application receives context from the hosting web or application server (and unlike SOAP doesn’t try to perform authentication but accepts credentials as part of the context), it makes sense to keep the REST application a lightweight as possible. In this case, decorators can be used to check access control in addition to URI handler registration.

As a proof of concept (and to learn how to write one style of Python decorator), the following test demonstrates access control through decorators. In a real application, credentials would be based on group in addition to user name, potentially source IP or host, and multiple handlers could be called to resolve the request — consider how to chain handlers, especially where ordering is important, or if an output XML document or data structure (dictionary) would be sufficient to get around handler ordering.

#!/usr/bin/env python

class deco(object):

    def __init__(self, **kwds):
        self.keywords = kwds

    def __call__(self, f):

        def setKeywords(*args):
            request = args[0]
            if request.getLocation() == self.keywords["handler"] and \
               request.getUser() in self.keywords["users"].split(","):
                print "Couldn’t handle request – not permitted"
        return setKeywords

@deco(handler="somelocation", users="bob,alice,charles")
def myHandler(request):
    print "myHandler args: " + str(request)
    print request.getUri()

class request(object):

    def getUri(self):
        return "/blah/blah/blah"

    def getLocation(self):
        return "somelocation"

    def getUser(self):
        #return "bob"
        return "chet"

req = request()

Other things to note:

  • decorator basics from Bruce Eckel
  • Lots of decorator code examples
  • Decorators are chained function calls.
  • Your decorator call (either the body of the decorator or the method __call__()) needs to return the decorator implementation function.

    def decorator(func):
      def func_impl(*args):
        # do something
        return func(*args)
      return func_impl
  • Your decorator implementation function needs to call the wrapped function with its arguments (note where arguments are passed in).

Comments are closed.