I'd like to use Tomcat's built-in authentication functionality (e.g. JDBCRealm + login page + web.xml security constraint). However I would like to extend it further if possible.
- Is there a session variable created for each authenticated user?
- I'd like to add an additional authentication step after Tomcat authentication is completed and before being granted access to which ever resource was requested... is this possible?
The closest things to session variables for authenticated users are the objects returned from the HttpServletRequest getRemoteUser() and getUserPrincipal() methods. However, the remote user ID is generally a pretty good key to use when an app wishes to extend the basic J2EE security infrastructure with refinements of its own.
The container-based authentication system is predicated on a common API and logic flow. The logic flow says that all incoming URLs are pattern-matched against the URL patterns defined in web.xml, and if the pattern matches a secured resource, the user's context is checked to see if the user has authenticated (logged in). If not, then the current URL request is shunted to the side, the login page is presented to the user, and its response routes to the server's security services, which invoke the configured Realm's authenticate() method. Realms use a common API, so they are plug-compatible.
If a user authenticates successfully, the Realm will be requested to construct and return an object implementing the UserPrincipal interface, and that object will be added to the user's context where it can then be retrieved by getUserPrincipal() as needed. Following all that, the original URL request is pulled off the sidelines and passed on for processing just as if login had never been requested. Except, of course, that now the remoteUser and userPrincipal objects are no longer null.
Adding additional parameters and/or functions to the login process is not supported. In fact, because the J2EE container security system supports Single Signon, there's not even an event that fires that alerts the webapp that the user has signed on. SSO means that actual login might have been via some other app on some other server and even in some other platform (such as IIS/.Net).
So anything like that would require customizing Tomcat itself.
An IDE is no substitute for an Intelligent Developer.
Joined: Oct 19, 2011
So I guess if I wanted to add additional steps after authenticate(), I would create a subclass of the Realm that I am using, override the authenticate method, call it via super.authenticate(), and then perform the custom steps?
Nothing so simple. Realms are implemented as plug-compatible components implementing a Tomcat-standard API Interface. The Realm Interface doesn't provide a "login" function, it provides the utilities that Tomcat's login code employs. To be precise, Tomcat will accept the userID and password from the login page, and pass them as parameters (and ONLY them) to the configured Realm's authenticate() method, which is simply a method that accepts the userID and password and returns a boolean match/no match value.
If Tomcat receives a positive response from the authenticate API method, it will then invoke the Realm API method that constructs a UserPrincipal object to contain the data needed for ongoing authorization functions. Which can be whatever the Realm wants, but is frequently a cached collection of roles appropriate for that user. Or a database connection to get them. etc.
Actually adding extra fields to the login forms or adding additional login pages cannot be done within the context of the Tomcat Realm architecture. Neither Tomcat nor J2EE in general has any standard for that. So you'd actually have to physically modify Tomcat itself.