[Zope-dev] Re: [Plone-developers] PAULA: bringing Zope 3's
authentication to Plone and beyond
Hermann Himmelbauer
dusty at qwer.tk
Wed Jul 16 04:20:58 EDT 2008
Am Mittwoch, 16. Juli 2008 05:48 schrieb Florian Friesdorf:
> On Mon, Jul 14, 2008 at 09:50:25AM +0200, Hermann Himmelbauer wrote:
> > (..)
> > 1) No way to pass PAU-related information to form-code: In PAU, the
> > (..)
> > 2) Lack of documentation: The entities "Principal, InternalPrincipal,
> > PrincipalInfo" are very confusing to a newbie, I still don't get the "big
> > picture".
>
> InternalPrincipal is a persistent object used to store the data of
> principals in a PrincipalFolder, PrincipalInfo is returned upon successfull
> authentication and handed to FoundPrincipalFactory, which extracts some
> information and returns Principal objects.
Ok, this is how I see it, too. But let me describe my understanding more
specific:
I see it that way that applications with authentication will normally have
something like a "user" object, which stores all related authentication/user
information. This user object may reside in a RDB, a text file, or, as here,
in a PrincipalFolder (as an InternalPrincipal).
If I understand it right, a Principal is an entity that is the result of an
authentication process and holds all needed information for authorization.
However, it is not designed to store user specific information, e.g. login
names, user names and the like.
And PrincipalInfo is somehow a specific aggregation of user data, which can be
used throughout the application. This object may have to be inherited to an
extended MyPrincipalInfo object, as many applications may need extra info
from this object.
So, both the Principal and PrincipalInfo objects have to be created out of the
user object, it is not possible to create a Principal out of a PrincipalInfo
and reverse.
Throughout my application, I have the following scenarios:
- I need to display some user data (e.g. in a "logged in" viewlet): I'd use
PrincipalInfo.
- I need to check for authorization somewhere in my application: I'd use the
Principal.
- I need to administer the user, e.g. change password etc.: I'd use the user
object (InternalPrincipal) for that.
- ???
In my application, all I have is the principal (request.principal). So I need
a viable way to retrieve PrincipalInfo and User/internalPrincipal objects.
How would I do that?
- user object: There seems to be no zope3 support for that yet - so it seems I
have to do this manually (some getUser(login) function, get the login from
request.principal.id[lenAUTH_PREFIX):], not very pretty, though.).
- PrincipalInfo: Don't really know - perhaps by somehow getting the PAU object
and iterating over the authentication modules, calling some getPrincipalInfo
method?
I personally would favour some adapters, e.g.:
InternalPrincipal = IInternalPrincipal(request)
PrincipalInfo = IPrincipalInfo(request)
The current documentation leaves many of the above points open, or at least,
did not describe them in a way so that I could understand them.
> > 3) Lack of plugins: No plugin for URL-rewriting, e.g. cookie-less
> > browsers (retrieving auth-information from URL) etc.
>
> I don't know about URL-rewriting, but you should be easily able to write
> your own credentials plugin to extract whatever you like from a request
> object.
Sure it's possible, that's what I did. But it was quite complicated and I had
to dig very deep into Zope3 code to do that. This is definitely no option for
a Zope developer who needs to quickly set up a cookie-less application.
> > How excactly should I cache user data so that a single browser request
> > does not lead to multiple RDB queries? And where in the big picture is
> > the "User" entity? (It's probably the InternalPrincipal object, I
> > assume)...
>
> You don't need InternalPrincipal objects, they are specific to
> PrincipalFolder, IMHO.
Well, yes and no - I need some user entity (which is located in the RDB),
which somehow resembles the InternalPrincipal object.
> I think you need:
> - custom authenticator plugin, that authenticates against RDB and has a
> dictionary as cache: key = login, value = password;
> - custom foundprinciplefactory, that generates Principal objects from RDB
> data, again using a simple key=login,value=Principal dictionary as cache; -
> eventually a custom credentials plugin, that for your point 3.
That's basically what I did. However, I did not yet implement caching, as some
things are not yet solved:
- What if the user changes his password? How would the cache update his data?
- What if a user is deleted?
So, it seems there needs to be some method that flushes the cache (e.g. if
user data changes). Maybe it makes sense to create an extra UserCache utility
that provides such methods.
This should be very well laid out before implementing, I think.
Currently, every simple HTTP request leads to 3 select statements on my user
table (due to authentication, prinipalInfo creation and the like). So, this
is something that needs to be solved by caching.
> > So I would very, very much suggest to dig into PAU first and fix those
> > shortcomings before porting it to Plone/Zope2.
>
> Exactly what I am doing :)
That's great!
If you have time, please don't forget scenarios, where user data is stored
outside Zope3 (e.g. RDB). I would very much appreciate, if Zope3 has some
built in support for that.
Best Regards,
Hermann
--
hermann at qwer.tk
GPG key ID: 299893C7 (on keyservers)
FP: 0124 2584 8809 EF2A DBF9 4902 64B4 D16B 2998 93C7
More information about the Zope-Dev
mailing list