Discussion:
[Twisted-Python] What are the relationships between twisted.cred.portal.IRealm, Portal and avatar
Wang Yan
2015-12-13 15:50:50 UTC
Permalink
I'm trying to use Twisted's HTTP basic authentication to control access to some protected resources.


According to some articles, it is necessary to use three important concepts: Realm, Portal and avatar. Now I'm wondering if the Realm and avatar is one to one correspondence.


Let's look at an example(http://www.red-bean.com/doc/python-twisted-web/examples/webguard.py):


import sys

from zope.interface import implements

from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse


class GuardedResource(resource.Resource):
"""
A resource which is protected by guard and requires authentication in order
to access.
"""
def getChild(self, path, request):
return self


def render(self, request):
return "Authorized!"



class SimpleRealm(object):
"""
A realm which gives out L{GuardedResource} instances for authenticated
users.
"""
implements(IRealm)

def requestAvatar(self, avatarId, mind, *interfaces):
if resource.IResource in interfaces:
return resource.IResource, GuardedResource(), lambda: None
raise NotImplementedError()



def main():
log.startLogging(sys.stdout)
checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe='blow')]
wrapper = guard.HTTPAuthSessionWrapper(
Portal(SimpleRealm(), checkers),
[guard.DigestCredentialFactory('md5', 'example.com')])
reactor.listenTCP(8889, server.Site(
resource = wrapper))
reactor.run()

if __name__ == '__main__':
main()


Of course I know the SimpleRealm is used to return the corresponding resource, e.g. GuardedResource in above example. However, I don't know what to do when there lots of resources to be guarded. For example, I have GuardedResource1, GuardedResource2 and GuardedResource3, maybe they need the same or different number of parameters when they are initialized; If so, is it necessary to implement SimpleRealm1, SimpleRealm2 and SimpleRealm3, respectively?
Glyph Lefkowitz
2015-12-17 11:45:45 UTC
Permalink
Post by Wang Yan
I'm trying to use Twisted's HTTP basic authentication to control access to some protected resources.
According to some articles, it is necessary to use three important concepts: Realm, Portal and avatar. Now I'm wondering if the Realm and avatar is one to one correspondence.
The idea is that a Realm represents an application, and an Avatar represents a single user's data within that application. This example is a bit oversimplified, since it doesn't provide any inputs to the user's data; most of the time, you'd want to retrieve a session or something based on the avatarID.
Post by Wang Yan
import sys
from zope.interface import implements
from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse
"""
A resource which is protected by guard and requires authentication in order
to access.
"""
return self
return "Authorized!"
"""
A realm which gives out L{GuardedResource} instances for authenticated
users.
"""
implements(IRealm)
return resource.IResource, GuardedResource(), lambda: None
raise NotImplementedError()
log.startLogging(sys.stdout)
checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe='blow')]
wrapper = guard.HTTPAuthSessionWrapper(
Portal(SimpleRealm(), checkers),
[guard.DigestCredentialFactory('md5', 'example.com')])
reactor.listenTCP(8889, server.Site(
resource = wrapper))
reactor.run()
main()
Of course I know the SimpleRealm is used to return the corresponding resource, e.g. GuardedResource in above example. However, I don't know what to do when there lots of resources to be guarded. For example, I have GuardedResource1, GuardedResource2 and GuardedResource3, maybe they need the same or different number of parameters when they are initialized; If so, is it necessary to implement SimpleRealm1, SimpleRealm2 and SimpleRealm3, respectively?
Rather than thinking of a resource as always existing and just needing to have a lock on it or not, consider the more flexible model (the one that cred actually implements) where a single Avatar object (in this case: the top IResource returned from SimpleRealm) is the top level of "everything the user has access to". In other words, 'GuardedResource' should have a 'getChild' method which makes the determination if the user they represent (really, at least the avatarId should be supplied to GuardedResource.__init__) has access to other resources, and return them if so, and appropriate errors if not.

Even the resources available to a not-logged-in user (see twisted.cred.credentials.Anonymous) is just another avatar, the one served up to unauthenticated people.

So, if you have https://myapp.example.com/a/b/secure/c/d <https://myapp.example.com/a/b/secure/c/d>, https://myapp.example.com/a/b/secure <https://myapp.example.com/a/b/secure> would be the guarded resource, and then SecureResource.getChild("c", ...) would return "c", which would in turn return "d" if the logged-in user has access to it.

Does this make sense?

Thanks for using Twisted,

-glyph

Loading...