How to retrieve a session scoped managed bean in a

2019-08-04 20:22发布

问题:

I'm having troubles in setting an Authorization Listener (that implements PhaseListener) to manage authentication and autorization.

More specifically, I set a session scoped bean called SessionBean:

@ManagedBean
@SessionScoped
public class SessionBean{

   private String loggedUser;

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

And in my 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>

In login() I make controls on username/password and if successful I set "loggedUser".

My AuthorizationListener is:

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 {
                 ...
            }
    }

    ...
}

And in the 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 -->

But I receive a null pointe sessionBean.getLoggedUser(). So, the SessionBean is still not created when the AuthorizationListener check the user. This is why I added a "if SessionBean doesn't exists, create it and put it in SessionMap", but still not working.

I'm not forced to use this approach for authentication and authorization, but what I need is to avoid "session.setAttribute("username", username). So any other strategy would be really apreciated. Thanks, Andrea

EDIT: as BalusC suggested, I edited the afterPhase method. Still having troubles with always null SessionBean.

回答1:

The @ManagedProperty works in @ManagedBean classes only. Your PhaseListener isn't.

You need to manually get it from the session map.

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

Note that it can be still null on the very first HTTP request.

The common approach, however, is to use a servlet Filter for the job, not a PhaseListener. The session scoped managed bean is available as a session attribute.

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


回答2:

Here in your code, in your phaseListener, you did not tell in which Phase exactly you would implement the code and you should call your managed bean. You should do this in RESTORE_VIEW Phase in AuthorizationListener override method getPhaseId(). See the following:

public PhaseId getPhaseId() {

        return PhaseId.RESTORE_VIEW;

    }

If your managed bean is still null, remove managed bean annotations, register it in faces_config, and use this helper method in phase listener to call the managed bean:

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

To call it in after phase method, use:

public void afterPhase(PhaseEvent event) {

SessionBean sessionBean =(SessionBean)resolveExpression("#{SessionBean}");
String currentUser = sessionBean.getLoggedUser();