尽管身份验证成功,request.getUserPrincipal() 在 RequestListener 中为 null

request.getUserPrincipal() is null in RequestListener despite that authentication succeeded

我们在更新和最新的 Tomcat 版本中遇到问题,这会阻止我们升级到比 7.0.22 更晚的版本。

我们将 FormBasedAuthentication 与自定义领域一起使用。

这是在 Windows.

上用 Tomcat 7.0.57 和 JDK 7u76 测试的

我的设置有一个调用 j_security servlet 的登录表单。自定义领域被调用并且身份验证成功,自定义主体被 returned。

Tomcat 然后将转发到受保护的资源,我们在 RequestListener 中捕获请求。

问题是,request.getUserPrincipal() return 为空。调试器显示,由 request.getSession(false) 编辑的会话包装器 return(SessionWrapper 的实例,包含 StandardSession)有一个字段“principal”,其中包含来自我的领域的主体 returned .

我在 bugzilla 中看到过关于 return 用户主体对非受保护请求的要求的讨论,但这里的请求是在调用受保护的资源。

任何关于为什么会发生这种情况的想法都会非常有帮助。实际上,我认为这是一个错误,请求未经过身份验证但仍被提供。

完全相同的设置在 Tomcat 7.0.12 上非常有效,我认为最高可达 7.0.22。

此致,

托马斯

这里是请求监听器的代码:

@Override
public void requestInitialized(ServletRequestEvent event) {
    if( log.isTraceEnabled() ) {
        log.trace( ">> requestInitialized" );
    }
    HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
    PortalRequest.current.set( request );
    HttpSession httpSession = null;
    GenericPrincipal genericPrincipal = (GenericPrincipal)request.getUserPrincipal();

// genericPrincipal is null, requestURI is pointing to a protected resource.

这是web.xml

中的表单认证配置
<welcome-file-list>
<welcome-file>jsp/main.jsp</welcome-file>
</welcome-file-list>

<security-constraint>
<display-name>PDiX Portal</display-name>
<web-resource-collection>
  <web-resource-name>PDX Portal Protected</web-resource-name>
  <url-pattern>/jsp/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>servlets</web-resource-name>
  <url-pattern>/servlet/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>GWT Resourcen</web-resource-name>
  <url-pattern>/StandardPortal/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>services</web-resource-name>
  <url-pattern>/delegating/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>ViewerServlet</web-resource-name>
  <url-pattern>/frameset</url-pattern>
  <url-pattern>/run</url-pattern>
</web-resource-collection>
<web-resource-collection>
  <web-resource-name>EngineServlet</web-resource-name>
  <url-pattern>/preview</url-pattern>
  <url-pattern>/download</url-pattern>
  <url-pattern>/parameter</url-pattern>
  <url-pattern>/document</url-pattern>
  <url-pattern>/output</url-pattern>
  <url-pattern>/extract</url-pattern>
</web-resource-collection>
<auth-constraint>
  <role-name>authenticatedUser</role-name>
</auth-constraint>

形式 PDX领域 /jsp/login.jsp /logout.jsp?error=true 认证用户

[更新问题以反映与请求侦听器的连接]

问题在 tomcat 用户列表中的 Konstantin Kolinko 的帮助下得到解决。

从 Tomcat 7.0.22 开始,身份验证发生在 servlet 请求侦听器被触发之后。这有副作用,请求侦听器不能再用于在会话中设置应用程序身份验证。

引用康斯坦丁的话:

There is the following change for 7.0.22 in the changelog file:

[quote] Correct a regression with the fix for 51653 that broke custom error pages for 4xx responses from the Authenticators. Error handling and request listeners are now handled in the StandardHostValve to ensure they wrap all Context level activity. (markt) [/quote]

所以,我的解决方案是找到另一种设置我的东西的方法,这很可能是一个过滤器。

我浏览了 Servlet 3.0 规范,想找到关于调用 requestInitialized() 时请求状态的任何提示,但没有给出具体要求(或者我没有找到)。

希望其他人也会觉得这有帮助。