I want to implement a Managed Bean Form Base Authentication, following the Java EE 6 Turorial I got to configure and build all the required elements, such as the login form, the error page, the web.xml security configuration and the Tomcat security realm (JDBC).
What is the Problem? The commandButton that is supposed to invoke the login() method in the Managed Bean is not working, I can see the constructor and the getters getting called but the login method and the setters are not.
What is curious? If I remove all the security related elements from the web.xml, restart the application and go directly to the login.xhtml form the login() method gets indeed called.
Conclusion? There must be something in the JSF implementation that is preventing this Form Based Authentication from working properly if a managed bean is used.
Note: The regular j_security_check Form Based Authentication (without using JSF) is working fine.
Any Ideas?
login.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view>
<h:head>
<title>Login Form</title>
</h:head>
<h:body>
<h2>Hello, please log in:</h2>
<h:form id="loginForm">
<h:messages style="color:red;margin:8px;" />
Username: <h:inputText value="#{loginBean.username}" />
<br />
Password: <h:inputSecret value="#{loginBean.password}" />
<br />
<h:commandButton id="loginButton" value="Login" action="#{loginBean.login}" />
</h:form>
</h:body>
</f:view>
</html>
LoginBean.java
package src;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2951813936936766650L;
public LoginBean() {
System.out.println("LoginBean()");
}
private String username;
private String password;
public String getUsername() {
System.out.println("getUsername() returning: " + this.username);
return this.username;
}
public void setUsername(String username) {
System.out.println("setUserName(" + username + ")");
this.username = username;
}
public String getPassword() {
System.out.println("getPassword() returning: " + this.password);
return this.password;
}
public void setPassword(String password) {
System.out.println("setPassword(" + password + ")");
this.password = password;
}
public String dummy() {
System.out.println("dummy()");
return "dummy";
}
public String login() {
System.out.println("login()");
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(this.username, this.password);
} catch (ServletException e) {
e.printStackTrace();
context.addMessage(null, new FacesMessage("Login failed."));
return "error";
}
return "index";
}
public void logout() {
System.out.println("logout()");
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.logout();
} catch (ServletException e) {
e.printStackTrace();
context.addMessage(null, new FacesMessage("Logout failed."));
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>FormBasedManagedBeanAuth</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>Tomcat7FormBasedJAAS</display-name>
<web-resource-collection>
<web-resource-name>secured</web-resource-name>
<description />
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description />
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/faces/login.xhtml</form-login-page>
<form-error-page>/faces/error.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description />
<role-name>user</role-name>
</security-role>
</web-app>
server.xml (tomcat, fragment)
<Realm className="org.apache.catalina.realm.JDBCRealm"
connectionName="database"
connectionPassword="password"
connectionURL="jdbc:mysql://localhost:3306/database"
driverName="com.mysql.jdbc.Driver"
roleNameCol="roleName"
userCredCol="password"
userNameCol="userName"
userRoleTable="user_role"
userTable="user"/>