1

我在设置授权侦听器(实现 PhaseListener)来管理身份验证和自动化时遇到了麻烦。

更具体地说,我设置了一个名为 SessionBean 的会话范围 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>

在 login() 中,我对用户名/密码进行控制,如果成功,我设置“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(“username”,username)。所以任何其他策略都会非常感激。谢谢,Andrea

编辑:正如 BalusC 所建议的,我编辑了 afterPhase 方法。始终为空的 SessionBean 仍然存在问题。

4

2 回答 2

3

@ManagedProperty仅在@ManagedBean课堂上工作。你PhaseListener的不是。

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

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

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

然而,常见的方法是使用 servletFilter来完成这项工作,而不是PhaseListener. 会话范围的托管 bean 可用作会话属性。

SessionBean sessionBean = (SessionBean) session.getAttribute("sessionBean");
于 2012-09-15T17:30:13.197 回答
0

在您的代码中,在您的 phaseListener 中,您没有确切说明您将在哪个阶段实现代码,您应该调用您的托管 bean。您应该在覆盖方法的RESTORE_VIEW阶段中执行此操作。请参阅以下内容:AuthorizationListenergetPhaseId()

public PhaseId getPhaseId() {

        return PhaseId.RESTORE_VIEW;

    }

如果您的托管 bean 仍然为空,请删除托管 bean 注释,将其注册到 中faces_config,并在阶段侦听器中使用此辅助方法来调用托管 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();      
于 2012-09-20T14:34:06.147 回答