通过过滤器设置 FacesMessage

Posted

技术标签:

【中文标题】通过过滤器设置 FacesMessage【英文标题】:Set FacesMessage by Filter 【发布时间】:2012-12-08 16:59:35 【问题描述】:

在我的 JSF 应用程序中,有一个 Filter 用于检查身份验证过程。当认证失败时,过滤器重定向到login.xhtml

如何将FacesMessageFilter 传递到我的登录页面?

虽然,我在下面用过,还是不行。

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

AuthenticationFilter.java

public class AuthenticationFilter implements Filter  
    private FilterConfig config;
    private ServletContext servletContext;

    public void init(FilterConfig filterConfig) 
        config = filterConfig;
        servletContext = config.getServletContext();
    

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException 
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpSession session = httpRequest.getSession();
        User user = (User) session.getAttribute(Constants.LOGIN_USER);
        if (user == null) 
            ...
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
         else if (!user.getRole().equals(Role.SYSTEM_ADMINISTRATOR)) 
            ....
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
         else 
            filterChain.doFilter(servletRequest, servletResponse);
        
        servletContext.log("Exiting the filter");
    

    public void destroy() 
        //Nothing to do.
    

【问题讨论】:

【参考方案1】:

FacesContextFacesServlet 创建。当您在过滤器中时,它还没有被调用。过滤器在 servlet 之前运行。因此,您永远无法使用过滤器中的FacesContext。另外,faces 消息是请求范围的,所以重定向会使它们消失。

login.xhtml<f:event type="preRenderView"> 期间自行设置。最简单的方法是让过滤器将其暂时放在会话范围内。

session.setAttribute("message", message);
httpResponse.sendRedirect(loginView);

然后在login.xhtml 的预渲染视图侦听器方法中将其从会话范围中删除:

String message = (String) externalContext.getSessionMap().remove("message");

if (message != null) 
    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

【讨论】:

【参考方案2】:

我在尝试在 EJB 计时器中获取 FacesContext 时遇到了类似的问题。 BalusC 在多个线程上指出不可能做到这一点。或者,您可以使用“ServletContextListener”,但 ScheduledExecutorService 不像 EJB 计时器那样定义调度。

无论如何,他提出的一个建议是实际向由托管 bean 支持的 JSF 页面发出 Web 请求,以利用我想用计时器设置的应用程序范围 bean 上的方法。

我提到这一点,因为您似乎可以做类似的事情,您可以将参数传递给 JSF 页面,其中包含您想要的消息和用户 IP 地址或其他内容。该页面可以由请求范围的 bean 支持,该 bean 中注入了一个应用程序范围的 bean,该 bean 将这些 bean 存储在以 IP 作为键的映射中。然后,当用户被重定向到登录页面时,该页面可以在请求范围的 bean 上调用获取错误消息方法,并在其中注入相同的应用程序范围的 bean,从而获取该 IP 或类似内容的错误消息。

无论如何,我确信 BalusC 的回答是足够的,比这更合适,但他的“只是从 ejb 计时器发出请求”的建议对我来说非常适合调度应用程序范围 bean 上的方法调用,我认为我可能会在这里提出它的可能用途。

@BalusC 你对我所指的帖子有任何想法吗?我找不到它。

【讨论】:

以上是关于通过过滤器设置 FacesMessage的主要内容,如果未能解决你的问题,请参考以下文章

NX二次开发-通过获取窗口句柄方式来设置类型过滤器EnumChildWindows

通过全局设置过滤器,就能让所有窗口都可移动,而不是都要继承指定QDialog

tibco Spotfire设置过滤器默认为8天

以编程方式为 JFileChooser 设置文件过滤器

php WordPress |通过设置Cookie来过滤帖子

如何将过滤器和订单数据设置到 DataTables 单元格