【问题标题】:How to read values from a JSF session map in a servlet filter?如何从 servlet 过滤器中的 JSF 会话映射中读取值?
【发布时间】:2023-03-04 10:24:01
【问题描述】:

要使用我的 Java EE webapp 进行身份验证,我有一个与 LoginBean 关联的 login.xhtml JSF 页面。如果用户提供了有效的登录详细信息,LoginBean 会将值保存到会话映射中:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("session-value", true);

现在我想在 LoginFilter(javax.servlet.Filter 的实现)中读取该值(称为“会话值”),但每次尝试访问该属性时,控制台都会告诉我我认为该属性为空:

 @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws Exception {
    HttpSession session = ((HttpServletRequest) request).getSession();
    Object attribute = session.getAttribute("session-value");

    if(attribute != null) {
      LOGGER.log(Level.INFO, ":)");
    } else {
      LOGGER.log(Level.INFO, "Attribute is null.");
    }

    chain.doFilter(request, response);
  }

难道不能通过调用 HttpServletRequest 的会话来访问 JSF 会话映射吗?

【问题讨论】:

    标签: session authentication servlets jsf-2 servlet-filters


    【解决方案1】:

    首先,是的,您可以在常规过滤器或 servlet 中访问 JSF 会话映射。它在底层会话中,并不特定于 JSF。

    处理你的 login.xhtml 的 FacesServlet(大概你有正确的 web.xml faces 相关配置),在你的 servlet 过滤器之后处理,而不是之前。如果您正在测试变量,则您看到的消息为空,因为该页面尚未登录用户。

    如果您要编写强制登录类型过滤器(检查会话中的某些内容并在该项目丢失时重定向到登录页面),那么您希望从过滤器中排除实际登录。该规范不支持 url 映射中的排除项,但您可以像这样向过滤器添加代码:

            HttpServletRequest req = ((HttpServletRequest)request);
    
        if (!req.getRequestURI().contains("login")) {
            //...Process your login code here - force redirect
        } //Otherwise it will allow the next filter or first servlet to process
    

    在登录页面处理并请求下一页(操作或强制导航)后,过滤器将再次处理并设置您的值。

    【讨论】:

    • 感谢您的回答。但是,当 JSF 会话映射将值存储在基础会话中时,如果在登录后第二次点击过滤器,我的访问过滤器应该可以从会话中读取这些值吗?因为当我第二次和第三次点击过滤器时,从会话中读取的值也为空。 :(
    • 是的,您将能够在过滤器的所有后续执行中看到“真”值。假设它们正在执行,您发布的代码 sn-ps 是可靠的。在 JSF 生命周期期间将项目存储到会话中,然后在 FacesServlet 上下文之外(在同一会话中)检索它们是标准做法。有很多代码示例看起来很像你的。我会在存储值的代码周围添加尽可能多的消息。在它完成执行任何其他代码之前,尝试在同一个 LoginBean 中检索它。
    • 好的。我这样做了。首先,执行过滤器,然后在会话中向 JSF 页面写入一个值,然后由过滤器的下一次执行读取会话值。但是,在过滤器的所有后续执行中,会话似乎都是空的。可能是我的 bean 或我的 JSF 页面清除了会话吗?我的 JSF 页面使用带有“Named”和“RequestScoped”注释的 Bean。
    • 听起来您验证了原始问题并发现您可以在常规 servlet 过滤器中读取从 JSF 编写的会话属性。至于为什么过滤器的后续调用停止显示该属性,我只能建议您跟踪所有代码并一遍又一遍地记录该值,直到找到它被清除的位置。此外,如果您调用类似:FacesContext.getCurrentInstance().getExternalContext().invalidateSession();,那么是的,您正在清除会话。
    猜你喜欢
    • 2012-06-14
    • 2012-01-03
    • 2012-04-24
    • 2011-04-10
    • 1970-01-01
    • 2013-10-05
    • 2012-10-16
    • 2012-02-19
    • 1970-01-01
    相关资源
    最近更新 更多