1

I have a web app with an authentication mechanism of type FORM, so when user asks for a protected resource login.jsp intercepts the request, sends j_username and j_password to the server where the user is authenticated and authorized to get that particular resource, which is sent back to the client.

During the following requests, j_username seems not to be stored anywhere (request parameter/attribute, session attribute) but you can get that value calling request.getUserPrincipal().getName().

Who and how is actually coupling that value with current user? Where is j_username really stored? My guess is that the application server is the one that is keeping track of the pairs [userid,sessionid] so that when request.getUserPrincipal().getName() is invoked it can send back the userid associated with the current session.

But this is just a guess, can anyone comfirm/refute?

Luigi Cortese
  • 10,841
  • 6
  • 37
  • 48

2 Answers2

3

My guess is that the application server is the one that is keeping track of the pairs [userid,sessionid] so that when request.getUserPrincipal().getName() is invoked it can send back the userid associated with the current session.

This is nowhere specified in the servlet specification. The "de facto" approach for FORM based authentication however indeed boils down to this. You can also easily confirm this by seeing the user principal disappear when you invalidate or expire the HTTP session.

The actual implementation depends on the servletcontainer used. In case of Tomcat, it's stored in its org.apache.catalina.Session class (representing the internal HttpSession facade), which has a getPrincipal() method which copies the Principal to every HttpServletRequest.

The place where it happens is the org.apache.catalina.authenticator.AuthenticatorBase, in the invoke() method. Below is an extract of relevance from Tomcat 10.0.21 source code:

509         if (cache) {
510             Principal principal = request.getUserPrincipal();
511             if (principal == null) {
512                 Session session = request.getSessionInternal(false);
513                 if (session != null) {
514                     principal = session.getPrincipal();
515                     if (principal != null) {
516                         if (log.isDebugEnabled()) {
517                             log.debug("We have cached auth type " + session.getAuthType() +
518                                     " for principal " + principal);
519                         }
520                         request.setAuthType(session.getAuthType());
521                         request.setUserPrincipal(principal);
522                     }
523                 }
524             }
525         }

At line 514 you can see it's extracted from HTTP session (at least, Tomcat's internal facade thereof which is not accessible via public API), and at line 521 you can see it being set on Tomcat's internal facade of the HTTP request which in turn is publicly accessible via HttpServletRequest#getUserPrincipal().

If you're curious how and when Session#setPrincipal() is called, head to register() method of the very same class.

All other servletcontainer implementations have a similar approach.

See also:

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Great answer as always. So, we can say that from the point of view of a (less curious) programmer, all you need to know and rely on is that `Principal` object is well anchored to the session, as long as you don't invalidate it. All the rest is vendor specific implementation, right? – Luigi Cortese Mar 14 '16 at 17:04
0

The webserver stores the UserPrincipal objects for each logged in user. The principal object is linked to sessionId. The sessionId is part of the cookie stored on the client side. So each time a user accesses the resource the sessionId is matched and respective UserPrincipal object is retreived. The implementation is a webserver dependent. In case of tomcat, the UserPrincipal object is created in the Realm class.

Here is the explaination.

Sandeep Sukhija
  • 1,156
  • 16
  • 30
  • I had already read that comment, but I was looking for something a bit more "official", maybe some actual reference if it exists... – Luigi Cortese Mar 14 '16 at 13:28