Как получить доступ к компоненту @Named в PhaseListener? - PullRequest
1 голос
/ 23 января 2012

Мы используем JBoss 7.1, MySQL / PostgreSQL DB, JSF 2.0 с компонентами CDI.

Я должен реализовать аутентификацию на основе БД по логину и паролю. У нас есть портал управления (администрирования). Когда клиент открывает запрещенную страницу без входа в систему, он должен перенаправить запрос на страницу login.*, если клиент не вошел в систему.

Я пытался сделать это с помощью PhaseListener. Я могу войти и выйти, но когда я пытаюсь открыть какую-то другую страницу, я столкнулся с проблемой: Я не могу получить бин @Named("user") public class UserManager в классе PhaseListener. Я пытался получить его, используя FacesContext, & EL ..., что все мне не помогло.

UserManager проверяет логин и сохраняет зарегистрированного пользователя как свойство current. При каждом запросе я хочу отмечать PhaseListener, если #{user.current} не null. Но я не могу получить бин #{user} в PhaseListener.

Как мне получить бин @Named в beforePhase() или afterPhase()?


Обновление : вот моя попытка:

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;
    }
}

Ответы [ 4 ]

7 голосов
/ 24 января 2012

Управляемый компонент CDI в области сеанса не сохраняется в сеансе HTTP так же, как управляемый компонент JSF в области сеанса. Управляемый JSF в рамках сеанса действительно сохраняется в сеансе под именем компонента в качестве ключа. Управляемый компонентом CDI в рамках сеанса, однако, абстрагируется дальше через другую карту в области сеанса.

Вам нужно получить его, оценивая 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 также уже есть в качестве аргумента метода.

2 голосов
/ 20 декабря 2012

Я использую следующий код, чтобы получить ссылку на компоненты CDI изнутри 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);
}

Таким образом, чтобы получить компонент, вы бы назвали его следующим образом:

DataManager dataManager = getBean(DataManager.class);

Бобом в этом случае является бин @Dependent, который используется в PhaseListener.

0 голосов
/ 17 февраля 2012

Другая возможность - использовать Лицевые швы .Это портативное расширение CDI, позволяющее наблюдать события лиц .

0 голосов
/ 24 января 2012

Надеюсь, это исправлено в следующей версии JSF, которая имеет реальную интеграцию CDI для этого материала. То, что вам нужно будет сделать (и сохранить переносимость), это поиск BeanManager через JNDI, а затем получить именованный компонент из BeanManager.

...