1
votes

I am developing jsf login and logout smaller web app.I see some problems.My logout method don't removed session and not working redirecting to login page.I have asked from stackoverflow.com.The Matt user answered Filter class to me.Then I researching Filter and page cache according Matt.I used to Filter's doFilter() method, in web.xml file etc..

Here is my code:

public class LoginFilter implements Filter {


@Override
public void init(FilterConfig config) throws ServletException {

}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
        FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    UserController userController = (UserController) request.getSession().getAttribute("user");


    if (userController == null || !userController.isLoggedIn()) {
        response.sendRedirect(request.getContextPath() + "/login.jsf");
    } else {
        chain.doFilter(request, response);
    }
}

@Override
public void destroy() {

}

}

And logout()

    public String logout() {

    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext ec = context.getExternalContext();
    final HttpServletRequest request = (HttpServletRequest) ec.getRequest();
    request.getSession(false).invalidate();
    return "logout";
}

And web.xml configuration:

<filter>
     <filter-name>loginFilter</filter-name>
     <filter-class>org.bis.logic.LoginFilter</filter-class>
</filter>
<filter-mapping>
     <filter-name>loginFilter</filter-name>
     <url-pattern>*.jsf</url-pattern>
</filter-mapping>

After logging I rendering home page.

<body>
 <!-- 
 #{ session.invalidate(); 
    response.sendRedirect("login.jsf");
  } -->
 <h:panelGrid rendered="#{userController.isLoggedIn()}">

 Hello Mr . #{userController.user.name}

<br />
<h:form>
    <p align="right">
          <h:commandLink action="#{userController.logout()}"value="Logout" />
    </p>
</h:form>
</h:panelGrid>
</body>

My userController managedBean class:

@ManagedBean(name = "userController")

@SessionScoped public class UserController {

private User user;

public UserController() {
    user = new User();
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

public static void addErrorMessage(String msg) {
    FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR,
            msg, msg);
    FacesContext.getCurrentInstance().addMessage(null, facesMsg);
}

public String authenticate() {

    if (user.getName().equals("admin") && user.getPassword().equals("")) {
        return "success";
    } else
        addErrorMessage(String
                .format("Username and Password didn't match !!!"));
    return "fail";

}

The page navigation xml:

    <navigation-rule>
    <from-view-id>/login.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/home.xhtml</to-view-id>
        <redirect />
    </navigation-case>
    <navigation-case>
        <from-outcome>fail</from-outcome>
        <to-view-id>/login.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>
<navigation-rule>
    <from-view-id>/home.xhtml</from-view-id>
    <navigation-case>
        <from-action>#{userController.logout()}</from-action>
        <from-outcome>logout</from-outcome>
        <to-view-id>/index.xhtml</to-view-id>
        <redirect />
    </navigation-case>
</navigation-rule>
1
THIS IS A ERROR PAGE PICTURE i.stack.imgur.com/YbkIV.pnguser1360797

1 Answers

3
votes

Your filter is running in an infinite redirect loop. The request on login.jsf will also invoke the filter. If the user is still not logged in, then it will redirect back to login.jsf which will in turn invoke the filter again, etcetera.

There are basically 2 ways to fix this:

  1. Make sure that login.jsf is not covered by the URL pattern of the filter. Collect all secured pages (expect of login.jsf!) in a separate folder like /app, /secured, /pages, etc and map the filter on that URL pattern instead, e.g. /app/*.

  2. Add an extra check which determines if the request is already requesting the login page and if so, then don't redirect to it again.

    String loginURL = request.getContextPath() + "/login.jsf";
    
    boolean loggedIn = userController != null && userController.isLoggedIn();
    boolean loginRequest = request.getRequestURI().equals(loginURL);
    
    if (loggedIn || loginRequest) {
        chain.doFilter(request, response);
    } else {
        response.sendRedirect(loginURL);
    }