如何在 PhaseListener 中访问 @Named bean?

发布于 2024-12-29 00:45:21 字数 2490 浏览 5 评论 0原文

我们使用 JBoss 7.1、MySQL/PostgreSQL DB、JSF 2.0 和 CDI beans。

我必须通过登录名和密码实现基于数据库的身份验证。我们有一个管理(行政)门户。当客户端在未登录的情况下打开受限页面时,如果客户端未登录,它应该将请求重定向到 login.* 页面。

我尝试通过使用 PhaseListener 来做到这一点。 我可以登录和注销,但是当我尝试打开另一个页面时遇到了问题: 我无法在 PhaseListener 类中获取 @Named("user") public class UserManager bean。我尝试使用 FacesContext 来获取它,& EL...,这一切都没有帮助我。

UserManager 验证登录并将登录的用户存储为 current 属性。对于每个请求,我想检查 PhaseListener 是否 #{user.current}null。但我无法在 PhaseListener 中获取 #{user} bean。

如何在 beforePhase()afterPhase() 中获取 @Named bean?


更新:这是我迄今为止的尝试:

private boolean loggedIn( FacesContext context ) throws IOException, ServletException
{
    LOGSTORE.debug( "loggedIn().2 " );

    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();

//  ELContext elContext = FacesContext.getCurrentInstance().getELContext();
//  UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
//      .getELResolver().getValue( elContext, null, "user" );

    HttpSession session = (HttpSession) context.getExternalContext().getSession( true );
    UserManager userManager = (UserManager) session.getAttribute( "user" );

//  UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get( "user" );

    if (!StringUtils.contains( ((HttpServletRequest) context.getExternalContext().getRequest())
        .getRequestURL().toString(), URL_SESSION_EXPIRED ))
    {

        if (userManager == null || !userManager.isLoggedIn())
        {
            LOGSTORE.debug( " userManager is " + (userManager == null ? "" : "not ") + " null" );
            if (userManager != null)
            {
                LOGSTORE.debug( " userManager.isLoggedIn() is "
                    + (userManager.isLoggedIn() ? "TRUE" : "FALSE") );
            }
            LOGSTORE.debug( " doPhaseFilter() - START REDIRECT " );
            response.sendRedirect( request.getContextPath() + "/" + homepage + "?auth-failed" );
        }
        return false;

    } else
    {
        LOGSTORE.debug( "loggedIn().3 it is " + homepage );
        return true;
    }
}

We are using JBoss 7.1, MySQL/PostgreSQL DB, JSF 2.0 with CDI beans.

I have to implement authentification based on DB by login and password. We have a managment (administration) portal. When the client opens a restricted page without being logged in, it should redirect the request to login.* page if the client is not logged in.

I have tried to do that by using a PhaseListener.
I can Login and Logout, but when I try to open some another page I ran into a problem:
I cannot get @Named("user") public class UserManager bean inside the PhaseListener class. I tried to get it by using FacesContext, & EL..., that all did not help me.

The UserManager validates the login and stores the logged in user as current property. On every request, I want to check in the PhaseListener if #{user.current} is not null. But I can't get the #{user} bean in the PhaseListener.

How can I get a @Named bean in beforePhase() or afterPhase()?


Update: here is my attempt so far:

private boolean loggedIn( FacesContext context ) throws IOException, ServletException
{
    LOGSTORE.debug( "loggedIn().2 " );

    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();

//  ELContext elContext = FacesContext.getCurrentInstance().getELContext();
//  UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
//      .getELResolver().getValue( elContext, null, "user" );

    HttpSession session = (HttpSession) context.getExternalContext().getSession( true );
    UserManager userManager = (UserManager) session.getAttribute( "user" );

//  UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get( "user" );

    if (!StringUtils.contains( ((HttpServletRequest) context.getExternalContext().getRequest())
        .getRequestURL().toString(), URL_SESSION_EXPIRED ))
    {

        if (userManager == null || !userManager.isLoggedIn())
        {
            LOGSTORE.debug( " userManager is " + (userManager == null ? "" : "not ") + " null" );
            if (userManager != null)
            {
                LOGSTORE.debug( " userManager.isLoggedIn() is "
                    + (userManager.isLoggedIn() ? "TRUE" : "FALSE") );
            }
            LOGSTORE.debug( " doPhaseFilter() - START REDIRECT " );
            response.sendRedirect( request.getContextPath() + "/" + homepage + "?auth-failed" );
        }
        return false;

    } else
    {
        LOGSTORE.debug( "loggedIn().3 it is " + homepage );
        return true;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

吻泪 2025-01-05 00:45:21

会话范围的 CDI 托管 Bean 与普通会话范围的 JSF 托管 Bean 不同,存储在 HTTP 会话中。管理的会话范围 JSF 确实通过 bean 名称作为键存储在会话中。然而,会话范围的 CDI 托管 Bean 通过会话范围中的另一个映射进一步抽象。

您需要通过以编程方式评估 EL 来获取它,而不是从会话映射中获取它。您的 EL 解析器尝试有一个错误,该值不包含任何 #{} 表达式。

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
    .getELResolver().getValue(elContext, null, "user");

相应地修复它:

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
    .getELResolver().getValue(elContext, null, "#{user}");

顺便说一句,上面的简写是 Application#evaluateExpressionGet()

UserManager userManager = context.getApplication()
    .evaluateExpressionGet(context, "#{user}", UserManager.class);

请注意,FacesContext context 也已经作为方法参数存在。

A session scoped CDI managed bean is not stored in the HTTP session the same way as a normal session scoped JSF managed bean. A session scoped JSF managed is indeed stored in the session by the bean name as key. A session scoped CDI managed bean is however abstracted further away through another map in the session scope.

You need to get it by evaluating EL programmatically instead of grabbing it from the session map. Your EL resolver attempt has one mistake, the value does not contain any #{} expression.

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
    .getELResolver().getValue(elContext, null, "user");

Fix it accordingly:

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
    .getELResolver().getValue(elContext, null, "#{user}");

By the way, a shorthand for the above is the Application#evaluateExpressionGet():

UserManager userManager = context.getApplication()
    .evaluateExpressionGet(context, "#{user}", UserManager.class);

Note that you've the FacesContext context also already there as method argument.

笑忘罢 2025-01-05 00:45:21

我使用以下代码从 PhaseListener 内部获取对 CDI bean 的引用。

public BeanManager getBeanManager() {
    BeanManager beanManager = null;
    try {
        InitialContext initialContext = new InitialContext();
        beanManager = (BeanManager) initialContext.lookup("java:comp/BeanManager");
    } catch (NamingException e) {
        logger.log(Level.SEVERE, "Couldn't get BeanManager through JNDI", e);
    }
    return beanManager;
}

public <T> T getBean(final Class<T> clazz) {
    BeanManager bm = getBeanManager();
    Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
    CreationalContext<T> ctx = bm.createCreationalContext(bean);
    return (T) bm.getReference(bean, clazz, ctx);
}

因此,要获取 bean,您可以像下面这样调用它。

DataManager dataManager = getBean(DataManager.class);

本例中的 bean 是一个在 PhaseListener 中使用的 @Dependent bean。

I use the following code to get a reference to the CDI beans from inside the PhaseListener.

public BeanManager getBeanManager() {
    BeanManager beanManager = null;
    try {
        InitialContext initialContext = new InitialContext();
        beanManager = (BeanManager) initialContext.lookup("java:comp/BeanManager");
    } catch (NamingException e) {
        logger.log(Level.SEVERE, "Couldn't get BeanManager through JNDI", e);
    }
    return beanManager;
}

public <T> T getBean(final Class<T> clazz) {
    BeanManager bm = getBeanManager();
    Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
    CreationalContext<T> ctx = bm.createCreationalContext(bean);
    return (T) bm.getReference(bean, clazz, ctx);
}

So to get the bean you would call it like the following.

DataManager dataManager = getBean(DataManager.class);

The bean in this case is a @Dependent bean which is being used in the PhaseListener.

眼泪也成诗 2025-01-05 00:45:21

希望这个问题在 JSF 的下一个版本中得到修复,该版本具有真正的 CDI 集成。您需要做的(并保持可移植性)是通过 JNDI 查找 BeanManager,然后从 BeanManager 获取指定的 bean。

Hopefully this is fixed in the next version of JSF which has real CDI integration for this stuff. What you will need to do (and maintain portability) is to lookup the BeanManager via JNDI, then get the named bean from the BeanManager.

春风十里 2025-01-05 00:45:21

另一种可能性是使用接缝面。它是一个便携式 CDI 扩展,允许您观察

Another posibility would be to use Seam Faces. It is a portable CDI extension and allows you to observe faces events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文