ZPublisherSecurity
The __allow_groups__ attribute
Have a look at BaseRequest.traverse, as this is where all the action occurs. Look for # Always perform authentication:
if hasattr(object, '__allow_groups__'): . . . v=groups.validate
__allow_groups__ is a UserFolder? instance and UserFolder? has a method called validate. In AccessControl?/User.py :
def validate(self, request, auth, roles)
where:
request._auth = environ['HTTP_AUTHORIZATION']
AccessControl?/User.py
UserFolders? are implemented by the User class.
User.identify returns name, password from the request using basic authentication scheme.
Sequence of events
The following is a rough sequence (note: there is a silly mode which allows no passwords. I have omitted it in this overview).
- ZPublisher?.BaseRequest?.traverse
- __before_publishing_traverse__ o traverse to object to be published o __bobo_traverse__ o getattr(object, entryname)
- found object to be published
- perform authorization checks
- v = userFolder = object.__allow_groups__
- user = userFolder.validate(request, auth, roles)
- name,password = User.identify(request.environ['HTTP_AUTHORIZATION'])
- user = User.authenticate(name, password, request)
- if self.authorize(user, a, c, n, v, roles): ...
- getSecurityManager().validate(a, c, n, v, roles) (see UserAuthorization)
- REQUEST['AUTHENTICATED_USER'] = user
Cookie Crumbler
Cookie Crumbler (in Plone) uses the ___before_publishing_traverse__ hook to set the REQUEST.environ['HTTP_AUTHORIZATION'] with the username and password. (The username, password were stored in a cookie).
Session-based security
For good security, we should not store the user name and password in a publicly accessible session variable and then hack the HTTP_AUTHORIZATION variable.
The username, and password could perhaps be stored in a private session variable (do they exist?). Alternatively, we could try to get validate() to return the User from the current session.