关于Java:登录后如何管理j_username值?

How is j_username value being managed once login is performed?

我有一个Web应用程序,该应用程序具有FORM类型的身份验证机制,因此当用户请求受保护的资源时,login.jsp截获该请求,将j_usernamej_password发送到对用户进行身份验证和授权的服务器获取该特定资源,将其发送回客户端。

在以下请求期间,j_username似乎没有存储在任何地方(请求参数/属性,会话属性),但是您可以通过调用request.getUserPrincipal().getName()获得该值。

谁以及如何将该值与当前用户实际耦合? j_username实际存储在哪里?我的猜测是,应用服务器是跟踪[userid,sessionid]对的服务器,因此在调用request.getUserPrincipal().getName()时,它可以发回与当前会话关联的用户ID。

但这只是一个猜测,任何人都可以确认/反驳吗?


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.

在servlet规范中没有指定。但是,基于FORM的身份验证的"事实上"方法实际上可以归结为这一点。您还可以通过使HTTP会话无效或过期时看到用户主体消失来轻松地确认这一点。

实际的实现取决于所使用的servlet容器。对于Tomcat,它存储在其org.apache.catalina.Session类(代表内部HttpSession外观)中,该类具有一个getPrincipal()方法,该方法将Principal复制到每个HttpServletRequest

发生的地方是invoke()方法中的org.apache.catalina.authenticator.AuthenticatorBase。以下是与Tomcat 8.0.24源代码相关的摘录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
426         if (cache) {
427             Principal principal = request.getUserPrincipal();
428             if (principal == null) {
429                 Session session = request.getSessionInternal(false);
430                 if (session != null) {
431                     principal = session.getPrincipal();
432                     if (principal != null) {
433                         if (log.isDebugEnabled()) {
434                             log.debug("We have cached auth type" +
435                                 session.getAuthType() +
436                                " for principal" +
437                                 session.getPrincipal());
438                         }
439                         request.setAuthType(session.getAuthType());
440                         request.setUserPrincipal(principal);
441                     }
442                 }
443             }
444         }

在第431行,您可以看到它是从HTTP会话中提取的(至少是Tomcat的内部外观,无法通过公共API访问),在440行,您可以看到它是在Tomcat的HTTP请求的内部外观上设置的。依次可通过HttpServletRequest#getUserPrincipal()公开访问。

如果您好奇如何以及何时调用Session#setPrincipal(),请转至同一类的register()方法。

所有其他servlet容器实现都具有类似的方法。

也可以看看:

  • 具有声明性安全性的JSP登录-实际身份验证如何进行?
  • 在哪里可以找到" j_security_check"?


Web服务器为每个登录用户存储UserPrincipal对象。主体对象链接到sessionId。 sessionId是存储在客户端的cookie的一部分。因此,每次用户访问资源时,都会对sessionId进行匹配,并获取各自的UserPrincipal对象。该实现取决于Web服务器。如果是tomcat,则在Realm类中创建UserPrincipal对象。

这里是解释。