1

I'm making a small website for a school project, but I'm struggling a bit with how to log a user out. The way I handle logging a user in is simply by writing their username to a @SessionScoped bean, and the using that to access the rest of their information. My plan to log them out is then to simply set the username back to null.

UserBean.java

@Data
@Named
@SessionScoped
public class UserBean implements Serializable {

    private String username;

    public boolean isLoggedIn() {
        return username != null;
    }

}

LoginController.java

@Named
@RequestScoped
public class LoginController {

    @Inject
    private UserBean userBean;

    @EJB
    private AccountDAO accountDAO;

    @Inject
    private LoginBackingBean loginBackingBean;


    public void validateEmailAndPassword() {

        if (accountDAO.usernameExist(userBean.getUsername())) {
            if (!(accountDAO.getAccountByUsername(userBean.getUsername())).getPassword().equals(loginBackingBean.getPassword())) {
                String msg = "Username or Password is incorrect";
                throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "", msg));
            }
        }
    }

    public void login() {
        userBean.setUsername(loginBackingBean.getUsername());
    }

}

LogoutController.java

@Named
@RequestScoped
public class LogoutController {

    @Inject
    private UserBean userBean;

    public void logout() {
        userBean.setUsername(null);
    }

}

xhtml insert that its seeing called from (menuDropdown.xhtml):

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets" 
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      >

    <h:body>
        <ui:composition>
            <button class="btn btn-outline-dark" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                menu
            </button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                <p:link class="dropdown-item" href="#">

                </p:link>
                <div class="dropdown-divider"></div>
                <div class="dropdown-item">
                    <h:commandButton class="btn btn-primary" value="Sign out" action="#{logoutController.logout}"></h:commandButton>
                </div>
            </div>
        </ui:composition>
    </h:body>
</html>

And this is how I call the logoutController:

<h:commandButton class="btn btn-primary" value="Sign out" action="#{logoutController.logout()}"></h:commandButton>

Right now the login method works great, and i can get the username from the bean by writing #{userBean.username}. However, for some reason nothing happens when i press the commandButton to log the user out. Am I calling it in an incorrect way or is there something else that is going on here?

Grebalb
  • 113
  • 1
  • 12
  • 1
    try to invalidate the session via `ExternalContext` and all data will be lost – fuggerjaki61 Mar 07 '20 at 16:10
  • How would I go about doing that? I tried: public void logout() throws IOException { ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ec.invalidateSession(); ec.redirect(ec.getRequestContextPath() + "/index.xhtml"); } without any success. – Grebalb Mar 07 '20 at 16:22
  • 1
    see [this](https://stackoverflow.com/questions/7148290/jsf-life-after-logout) question and if you want I can provide a solution – fuggerjaki61 Mar 07 '20 at 16:24
  • Hmm, still can't get it to work. Can there be something wrong with my commandButton? nothing seems to be firing when I hit it. I don't get a page to reload or anything. – Grebalb Mar 07 '20 at 16:38
  • 1
    try to make `@RequestScoped` to `@ViewScoped` and try to add a `System.out.println("some text");` to see if the method is invoked – fuggerjaki61 Mar 07 '20 at 16:40
  • Nothing is printed to the console so I guess thE method isn't being invoked for some reason? – Grebalb Mar 07 '20 at 16:45
  • 1
    have you already changed `@RequestScoped`? are there any exceptions in the browsers console (F12)? – fuggerjaki61 Mar 07 '20 at 16:46
  • Yeah, I made it ´@viewScoped` and ìmplements `implements Serializable`. Nothing is happening in the browser console. – Grebalb Mar 07 '20 at 16:48
  • 1
    see [possible causes](https://stackoverflow.com/questions/2118656/commandbutton-commandlink-ajax-action-listener-method-not-invoked-or-input-value) – fuggerjaki61 Mar 07 '20 at 16:49
  • Thank you! I placed it in an ``tag instead of the `
    ` and the it worked!
    – Grebalb Mar 07 '20 at 16:55

1 Answers1

1

To effectively logout an user the session should be destroyed and with it all possibilties to remain logged in (deleting cookies, etc.). To destroy the session the logout method must contain this:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

This invalidates (destroys) the current session and all values will be reset and if the user remains on the side a new session with default and new id values will be created.

Also redirecting to a public view is a good idea so the user does not see a 403 page. Then just return:

return "/index?faces-redirect=true";

Some Lecture:

JSF life after logout

How to create, access and destroy session in JSF managed bean?

Performing user authentication in Java EE / JSF using j_security_check

fuggerjaki61
  • 822
  • 1
  • 11
  • 24
  • Thank you! This in combination with changing out the `
    `tags with ``tags around the button did the trick
    – Grebalb Mar 07 '20 at 17:00