Jsf Wildfly Openshift上的ViewExpiredException

Jsf Wildfly Openshift上的ViewExpiredException,jsf,login,viewexpiredexception,Jsf,Login,Viewexpiredexception,我在Openshift wildfly 8.1上托管了示例J2EE webapp,在这里我得到了ViewExpiredException。之后,提供错误页面并重定向到此异常的登录页面。成功登录后,登录页面仍无法重新定向到受保护的页面 这是使用(user1/1234)登录的应用程序 请在下面找到代码 faces-config.xml <?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://ja

我在Openshift wildfly 8.1上托管了示例J2EE webapp,在这里我得到了ViewExpiredException。之后,提供错误页面并重定向到此异常的登录页面。成功登录后,登录页面仍无法重新定向到受保护的页面

这是使用(user1/1234)登录的应用程序

请在下面找到代码

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
    <navigation-rule>
        <display-name>Login.xhtml</display-name>
        <from-view-id>/Login.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>failure</from-outcome>
            <to-view-id>/Login.xhtml</to-view-id>
            <redirect />
        </navigation-case>
    </navigation-rule>
    <factory>
        <exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
    </factory>
</faces-config>
LoginController.java

package com.prime.controller;

import java.io.IOException;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;

import com.prime.util.DateUtility;

/**
 * Login Controller class allows only authenticated users to log in to the web
 * application.
 *
 * @author prime
 */
@Named
@SessionScoped
public class LoginController implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private transient Logger logger;

    @Inject
    FacesContext facesContext;

    @NotNull
    private String username;

    @NotNull
    private String password;

    private String email; 

    /**
     * Creates a new instance of LoginController
     */
    public LoginController() {
    }

    //  Getters and Setters
    /**
     * @return username
     */
    public String getUsername() {
        return username;
    }

    /**
     *
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     *
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     *
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }


    /**
     * Listen for button clicks on the #{loginController.login} action,
     * validates the username and password entered by the user and navigates to
     * the appropriate page.
     *
     * @param actionEvent
     */
    public void login(ActionEvent actionEvent) {

        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        try {

            try{
                MessageDigest md = java.security.MessageDigest.getInstance("MD5");
                md.update(password.getBytes("UTF-8"));
                byte[] passwordDigest = md.digest();
                @SuppressWarnings("restriction")
                String encodedPasswordHash = new sun.misc.BASE64Encoder().encode(passwordDigest);
                logger.log(Level.INFO, "Encripted Password {0}" ,encodedPasswordHash);
            } catch(Exception e){
                e.printStackTrace();
            }

            // Checks if username and password are valid if not throws a ServletException
            request.login(username, password);
            // gets the user principle and navigates to the appropriate page
            Principal principal = request.getUserPrincipal();

            String navigateString = "/user/expirepage.xhtml"; 

            try {
                logger.log(Level.INFO, "User ({0}) loging in #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
                facesContext.getExternalContext().redirect(request.getContextPath() + navigateString);
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "IOException, Login Controller" + "Username : " + principal.getName(), ex);

            }
        } catch (ServletException e) {            
            logger.log(Level.SEVERE, "Login Controller: The username or password you provided does not match our records.");            
            facesContext.validationFailed();
        }
    }

    /**
     * Listen for logout button clicks on the #{loginController.logout} action
     * and navigates to login screen.
     */
    public void logout(ActionEvent actionEvent) {

        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        logger.log(Level.INFO, "User ({0}) loging out #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
        if (session != null) {
            session.invalidate();
        }
        facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, "/Login.xhtml?faces-redirect=true");

    }


}
/
上述原因导致了问题。如果将上下文根更改为任何其他根,则不会出现问题,例如:

<context-root>/noproblem</context-root>
/n问题
我认为自从WildFly 8.0 RC1发布以来,出现了一个bug。在WildFly 8.0 Beta1和JBoss 7上还可以

如果上下文根为“/”,则服务器会在每个浏览器窗口中创建多个会话。每个子文本/子文件夹都有自己的会话。这会导致你的问题


我在本地机器上观察到它,而不是在云中。

当根上下文为“/”时,问题是由于多个JSessionid引起的。我在jboss-web.xml上添加了以下配置,解决了这个问题

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <context-root>/</context-root>
    <security-domain>java:/jaas/jdbc-security-domain</security-domain>
</jboss-web>
<?xml version="1.0"?>
<jboss-web>
    <session-config>
       <cookie-config>
          <path>/</path>
       </cookie-config>
    </session-config>
</jboss-web>
<xml>

/
package com.prime.filter;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.application.ResourceHandler;
import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * To prevent user from going back to Login page if the user already logged in
 *
 * @author prime
 */
@WebFilter(urlPatterns="/Login.xhtml")
public class LoginPageFilter implements Filter {

    @Inject
    private transient Logger logger;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        if (request.getUserPrincipal() != null) { //If user is already authenticated

            String navigateString = "/user/expirepage.xhtml";

            String url = request.getContextPath() + navigateString;
            response.sendRedirect(url);
            logger.log(Level.INFO, "Redirect to {0}",url);
        } else {
            if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                response.setHeader("Pragma", "no-cache");
                response.setDateHeader("Expires", 0); 
                logger.log(Level.INFO, "Clear Cache {0}",response.toString());
            }   
            filterChain.doFilter(servletRequest, response);
        }
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

}
package com.prime.controller;

import java.io.IOException;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;

import com.prime.util.DateUtility;

/**
 * Login Controller class allows only authenticated users to log in to the web
 * application.
 *
 * @author prime
 */
@Named
@SessionScoped
public class LoginController implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private transient Logger logger;

    @Inject
    FacesContext facesContext;

    @NotNull
    private String username;

    @NotNull
    private String password;

    private String email; 

    /**
     * Creates a new instance of LoginController
     */
    public LoginController() {
    }

    //  Getters and Setters
    /**
     * @return username
     */
    public String getUsername() {
        return username;
    }

    /**
     *
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     *
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     *
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }


    /**
     * Listen for button clicks on the #{loginController.login} action,
     * validates the username and password entered by the user and navigates to
     * the appropriate page.
     *
     * @param actionEvent
     */
    public void login(ActionEvent actionEvent) {

        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        try {

            try{
                MessageDigest md = java.security.MessageDigest.getInstance("MD5");
                md.update(password.getBytes("UTF-8"));
                byte[] passwordDigest = md.digest();
                @SuppressWarnings("restriction")
                String encodedPasswordHash = new sun.misc.BASE64Encoder().encode(passwordDigest);
                logger.log(Level.INFO, "Encripted Password {0}" ,encodedPasswordHash);
            } catch(Exception e){
                e.printStackTrace();
            }

            // Checks if username and password are valid if not throws a ServletException
            request.login(username, password);
            // gets the user principle and navigates to the appropriate page
            Principal principal = request.getUserPrincipal();

            String navigateString = "/user/expirepage.xhtml"; 

            try {
                logger.log(Level.INFO, "User ({0}) loging in #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
                facesContext.getExternalContext().redirect(request.getContextPath() + navigateString);
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "IOException, Login Controller" + "Username : " + principal.getName(), ex);

            }
        } catch (ServletException e) {            
            logger.log(Level.SEVERE, "Login Controller: The username or password you provided does not match our records.");            
            facesContext.validationFailed();
        }
    }

    /**
     * Listen for logout button clicks on the #{loginController.logout} action
     * and navigates to login screen.
     */
    public void logout(ActionEvent actionEvent) {

        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        logger.log(Level.INFO, "User ({0}) loging out #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
        if (session != null) {
            session.invalidate();
        }
        facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, "/Login.xhtml?faces-redirect=true");

    }


}
<context-root>/</context-root>
<context-root>/noproblem</context-root>
<?xml version="1.0"?>
<jboss-web>
    <session-config>
       <cookie-config>
          <path>/</path>
       </cookie-config>
    </session-config>
</jboss-web>
<xml>