Jsf Wildfly Openshift上的ViewExpiredException
我在Openshift wildfly 8.1上托管了示例J2EE webapp,在这里我得到了ViewExpiredException。之后,提供错误页面并重定向到此异常的登录页面。成功登录后,登录页面仍无法重新定向到受保护的页面 这是使用(user1/1234)登录的应用程序 请在下面找到代码 faces-config.xmlJsf 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
<?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>