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?
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.