2012-09-15 57 views
0

我在设置Authorization Listener(实现PhaseListener)来管理身份验证和自动化方面遇到麻烦。如何在PhaseListener中检索会话范围的托管bean?

更具体地说,我设置会话范围的bean称为会话Bean:

@ManagedBean 
@SessionScoped 
public class SessionBean{ 

    private String loggedUser; 

    public SessionBean(){ 
    logger.info("Sono nel costruttore di SessionBean()"); 
    } 
    public String login(){ 
     .... 
    } 
    ... 
} 

在我的sun-web.xml中:

<managed-bean> 
    <managed-bean-name>SessionBean</managed-bean-name> 
    <managed-bean-class>it.uniroma3.acme.auction.bean.SessionBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
    </managed-bean> 

在登录()我就用户名/密码控件如果成功,我设置“loggedUser”。

我AuthorizationListener是:

public class AuthorizationListener implements PhaseListener { 

    private String currentUser; 

    private SessionBean sessionBean; 

    public void afterPhase(PhaseEvent event) { 
     SessionBean sessionBean = (SessionBean)event.getFacesContext().getExternalContext().getSessionMap().get("SessionBean"); 
     String currentUser = sessionBean.getLoggedUser(); 

     if (sessionBean != null) { 
      ... 
       String currentUser = sessionBean.getLoggedUser(); 
     } 
      else { 
       ... 
      } 
    } 

    ... 
} 

而在sun-web.xml中:

<!-- Authentication and authorization block starting --> 
    <lifecycle> 
     <phase-listener>AuthorizationListener</phase-listener> 
    </lifecycle> 
    <navigation-rule> 
     <from-view-id>/*</from-view-id> 
     <navigation-case> 
      <from-outcome>loginPage</from-outcome> 
      <to-view-id>login.jsf</to-view-id> 
     </navigation-case> 
    </navigation-rule> 
    <!-- Authentication and authorization block ending --> 

但是我收到一个空足尖sessionBean.getLoggedUser()。因此,当AuthorizationListener检查用户时,SessionBean仍未创建。这就是为什么我添加了“如果SessionBean不存在,创建并将其放入SessionMap”,但仍然无法工作。

我不是被迫使用这种方法进行身份验证和授权,但我需要的是避免“session.setAttribute(”用户名”,用户名)。因此,任何其他的策略将是非常apreciated。 谢谢, 安德烈

编辑:作为BalusC建议,我只@ManagedBean类编辑afterPhase方法仍然具有总是空的SessionBean烦恼

回答

2

@ManagedProperty作品你PhaseListener

呦。。你需要手动从会话映射中获取它。

SessionBean sessionBean = (SessionBean) event.getFacesContext() 
    .getExternalContext().getSessionMap().get("SessionBean"); 

注意,它可以仍然null对第一个HTTP请求。

但是,常见的做法是使用servlet Filter作为作业,而不是PhaseListener。会话范围的托管bean可用作会话属性。

SessionBean sessionBean = (SessionBean) session.getAttribute("sessionBean"); 
+0

谢谢,BalusC。然而,我遇到了一个** always ** null的“SessionBean”问题(我在你的建议之后更新了这个问题):在第一次打击中我期望一个空值,但是当听众允许我完成登录表单时,它旁边的bean(SessionBean)应该被隔离。顺便说一句,我也interesten在过滤器的方法,你能建议我一些链接或资源在哪里学习它?谢谢,安德烈 – andreaxi

+1

BalusC,我跟着[这个步骤](http://stackoverflow.com/questions/7979839/how-do-a-web-filter-in-jsf-2)和访问会话。但是,当我在一个bean中,并且我需要使用FacesContext.getCurrentInstance()。getExternalContext()。redirect(...)从actionListener方法重定向到页面时,它会导致请求参数丢失。我如何重定向保存请求/响应/会话(不仅仅是重定向,我需要一个前进)?谢谢,Andrea – andreaxi

+1

感谢您的贡献[这里](http://stackoverflow.com/questions/3888710/jsf-1- 2-difference-between-in-action-and-actionlistener)解决了这个问题:我不需要actionListener,因为我必须使用一个动作(它涉及到业务任务)。 – andreaxi

0
在你的代码

在这里,你的PhaseListener,你没有知道在哪儿阶段正是你所执行的代码,你应该打电话给你的托管bean。您应该在RESTORE_VIEW阶段执行AuthorizationListener替代方法getPhaseId()。看到以下内容:

public PhaseId getPhaseId() { 

     return PhaseId.RESTORE_VIEW; 

    } 

如果你的托管bean仍然是空,除去托管bean注释,在faces_config注册,并使用这个辅助方法phase监听器调用托管bean:

public static Object resolveExpression(String expression) { 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    Application app = ctx.getApplication(); 
    ValueBinding bind = app.createValueBinding(expression); 
    return bind.getValue(ctx); 
} 

要在阶段法后调用它,请使用:

public void afterPhase(PhaseEvent event) { 

SessionBean sessionBean =(SessionBean)resolveExpression("#{SessionBean}"); 
String currentUser = sessionBean.getLoggedUser();  
相关问题