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

Reply via email to