1

我正在尝试检索由 JSF2 支持 bean(或 servlet)中的自定义 Tomcat Valve 设置的值。我看不到如何做到这一点,也找不到使用 Google 的任何示例。

背景:在我的 JSF2 Web 应用程序中,我需要为每个用户添加一个时区属性。实现这一点的最简单方法是在用户个人资料页面中添加一个时区下拉菜单,以便每个用户都可以选择合适的时区。然而,这可以自动化,因为浏览器中的一些 JavaScript能够自动计算时区。

所以我在我的 Tomcat 登录页面上放置了一个新参数,它提供了这个值,Web 应用程序可以在登录时捕获它。Tomcat 表单身份验证机制负责处理登录页面(通过 HTTP POST 到 j_security_check)。我实现了一个 Java EE Servlet 过滤器来捕获这个,但是 Tomcat 的登录机制绕过了过滤器,所以这段代码永远不会看到 POST 到 j_security_check。

我现在已经实现了一个 Tomcat Valve,我可以成功地将 POST 捕获到 j_security_check。在代码中,我提取时区值并将其放在......在哪里?

我知道阀门(必须放在 TOMCAT_HOME/lib 中)与我的常规 JSF2 代码具有不同的类加载器。这意味着我无法从我的 JSF2 代码访问阀门的任何静态成员。

因此,受到标准 Tomcat 阀门源代码的启发,我在阀门中尝试了这个:

final org.apache.catalina.Session session = request.getSessionInternal(true);
session.setNote("com.conexa.timezoneOffset", timezoneOffset);

但是,在我的 JSF2 托管 bean 中,我无法获得对 org.apache.catalina.Session 的引用。

此代码返回一个 StandardSessionFacade 类型的对象,它不允许我访问 org.apache.catalina.Session。

FacesContext.getCurrentInstance().getExternalContext().getSession(false);

在调试模式下运行,我已经能够找到 org.apache.catalina.Session,但 'notes' 字段实际上是空的。

我还认为 Tomcat 可能会使用一个会话进行登录,然后再创建一个新会话(可能与Session Fixation Protection相关)。如果确实如此,我认为问题会更加复杂。

任何 Tomcat 大师有什么好主意吗?普通 servlet 的解决方案也是可以接受的,因为我确信我能够适应它。

4

1 回答 1

3

好的,我知道了!

在阀门代码中:

final HttpSession session = request.getSession(true);
session.setAttribute("timezoneOffset", timezoneOffset);

在 JSF2 代码中:

final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
final String timezoneOffsetStr = "" + externalContext.getSessionMap().get("timezoneOffset");
于 2012-08-06T13:22:53.317 回答