Hi there,
finally, I got my first Tomcat enhancement ready. You can view its code
at my Tomcat fork on GitHub:
https://github.com/cklein05/tomcat/tree/session-manager-persist-authentication
Before I'm opening an enhancement in Tomcat's Bugzilla, maybe, Mark and
Christopher (or whoever else is interested), could you please have a
quick look at the code?
BTW, recent versions of Tomcat do no longer save and store passwords in
GenericPrincipal. That makes using this enhancement even less critical.
Some brief description of what I've done:
1. The new boolean option 'persistAuthentication' is implemented in
ManagerBase and so can be configured for StandardManager or
PersistentManager (defaults to false). Also added this to
mbeans-descriptor.xml, so it's writable through JMX.
2. That option is set for any new StandardSession upon creation (in
method ManagerBase.createSession(String)). Once a session got this
option, it's not being changed during the session's lifetime.
3. In StandardSession, method doWriteObject writes authentication
information (authType and principal) only, if 'persistAuthentication' is
true, the session is authenticated (authType or principal != null) and
principal is serializable.
4. The "is principal serializable" test is, by default, a deep
(expensive?) check, which actually serializes the whole principal object
to an ObjectOutputStream backed by a new NullInputStream, which just
discards all bytes written. This check can be skipped by setting system
property
org.apache.catalina.session.StandardSession.PRINCIPAL_SERIALIZABLE_CHECK
to false (defaults to true, however). If skipped, the principal is
considered serializable if (principal instanceof Serializable). That's
how the session's attribute values are checked for being serializable or
not.
However, that is odd, if such a serialized object has a child object
which is not serializable. In that case, the ObjectOutputStream is left
in an inconsistent state and no so called fatal exception code is
written to the stream (that is, when reading such a stream, no
WriteAbortedException is not thrown for such an error).
5. A Boolean object is used as a tag/marker that determines, whether
authentication information is present id the stream or not. If none of
the above conditions are met, both authType and principal are not
serialized (than, only the initial Boolean false marker has been emitted
to the stream).
BTW, the Boolean false marker is not even required (if there is no
authentication information in the stream) since the reading code works
fine without any Boolean in the stream. So emitting Boolean false for
signalling "no auth info" is actually optional (we could consider
omitting it).
6. When sessions are loaded, ManagerBase provides a
org.apache.catalina.util.CustomObjectInputStream instance to read
sessions from. That instance is configured with the session's
sessionAttributeValueClassNamePattern property. This essentially defines
the classes, session attribute values may consist of. This pattern
defaults to "java\\.lang\\.(?:Boolean|Integer|Long|Number|String)", so
only attributes with these simple types can be loaded from a session.
That filter pattern is only in effect, if a security manager is active,
or if a pattern has been configured for the manager (e.g. in context.xml).
Currently, however, all session data (including its base properties like
creationTime, isNew, isValid etc) is loaded with that filter mechanism
in place. Since those so called 'scalar instance properties' actually
only consist of those simple types, that was not a problem.
However, loading the serialized principal from the object stream is now
subject to that filter mechanism (BTW, HA's DeltaManager and
DeltaSession just do not utilize the CustomObjectInputStream).
Since, as the name implies, the sessionAttributeValueClassNamePattern
applies to attribute values only, I decided to give the
CustomObjectInputStream a boolean 'filterActive' property, which is set
to true, just before StandardSession starts deserializing attributes.
The initial value of 'filterActive' can be specified though the
constructor, to which both StandardManager and StoreBase pass false
(actually, only StandardManager and PersistenManager (through StoreBase)
do use the CustomObjectInputStream class).
7. Conclusion
- Tomcat still builds with that enhancement in place
- The enhancement obviously works as expected
- Minor decisions can still be made (e.g. pull NullInputStream into a
new file, maybe in ...catalina.util)
- What about the Tomcat documentation? Where to document all this?
Carsten
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org