I tried solutions from topics with same issue but that didn't work for me. So here is my story. I created very simple web project:
project
Here the code:
package user.bean;
import javax.annotation.ManagedBean;
#ManagedBean
public class User {
private String firstName;
private String lastName;
private String email;
User() {
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
First JSF:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>User Registration Form</title>
<style>
.error {color:red}
</style>
</h:head>
<h:body>
<h:form>
<h:messages styleClass="error"/>
First Name: <h:inputText value="#{user.firstName}"
label="First name"/>
<br/><br/>
Last Name: <h:inputText value="#{user.lastName}"
label="Last name"
required="true"/>
<br/><br/>
Email: <h:inputText value="#{user.email}"
label="Email"
required="true"/>
<br/><br/>
<h:commandButton value="Submit" action="user_response"/>
</h:form>
</h:body>
</html>
Second JSF:
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>User Confirmation</title>
</h:head>
<h:body>
<h:form>
User is confirmed: #{user.firstName} #{user.lastName}
<br/><br/>
Email: #{user.email}
</h:form>
</h:body>
</html>
At
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
I have: NLS missing message: CANNOT_FIND_FACELET_TAGLIB in:
org.eclipse.jst.jsf.core.validation.internal.facelet.messages
I tried:
Close/reopen project.
Rightclick project > Validate.
Project > Clean... and clean selected project.
Restart Eclipse.
Its didnt worked.
When I run it I faced: HTTP Status 404
So I tried this:
Click on Window > Show view > Server or right click on the server in
"Servers" view, select "Properties".
In the "General" panel, click on the "Switch Location" button.
The "Location: [workspace metadata]" should replace by something else.
Open the Overview screen for the server by double clicking it.
In the Server locations tab , select "Use Tomcat location".
Save the configurations and restart the Server.
Than I add JSF 2.2 (Mojarra 2.2.0) by properties -> Java Build Path. No changes. So I delete it from Build Path and add to WEB-INF->lib. Run on server and face: HTTP Status 500 - Servlet.init() for servlet Faces Servlet threw exception. I added url-pattern and listener to my web.xmp:
<?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" 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>JSF</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<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>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
</web-app>
and faced HTTP Status 404 - /JSF/user_form.xhtml
Well I'm complete newbe right now and will be very greatful for little help here. Thanks.
Related
This question already has answers here:
Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable
(18 answers)
Closed 6 years ago.
I am new to jsf and am getting a parse error when running a simple form. The error says "/enternameform.xhtml #17,59 value="#{register.firstName}": Target Unreachable, identifier 'register' resolved to null"
My code is below
enternameform.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>registration form</title>
<link href="./css/styles.css" rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h1 class="title">Enter Name and Register</h1>
<br/>
<fieldset>
<legend>Please Enter Name here</legend>
<h:form>
<!-- Your form elements here -->
First Name: <h:inputText value="#{register.firstName}"/> <br/>
Last Name: <h:inputText value="#{register.lastName}"/><br/>
<h:commandButton value="go ahead" action="#{register.fullName}"/>
</h:form>
</fieldset>
</div>
</h:body></html>
Register.java
package registrationform;
import javax.faces.bean.ManagedBean;
#ManagedBean
public class Register {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String fullName (){
if(isMissing(firstName)|| isMissing(lastName)){
return("missing");
}else{
return("registrationsuccess");
}
}
private boolean isMissing(String name){
return (name.trim().isEmpty());
}
}
missing.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>missing</title>
<link href="./css/styles.css" rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<h1 class="title">Please enter both First and Last Name to Register</h1>
Try again here
</h:body></html>
registrationsuccess.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>registrationsuccess</title>
<link href="./css/styles.css" rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<h1 class="title">You have completed registration</h1>
First Name: #{register.firstName} <br/>
Last Name:#{register.lastName}
</h:body></html>
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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- The bare minimum needed for JSF 2.2 is a servlet 2.5 or later
declaration (this uses 3.0) and the mapping for the FacesServlet.
Setting PROJECT_STAGE to Development is highly recommended
during initial development so that you get more helpful
error messages. Whether you want server-side state saving
(default) or client-side is a more complicated question:
client-side uses more bandwidth but fewer server resources.
Client-side also helps to avoid the dreaded view expired exceptions.
From JSF 2 and PrimeFaces tutorial
at http://www.coreservlets.com/JSF-Tutorial/jsf2/
-->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<description>State saving method: 'client' or 'server' (default). See JSF Specification section 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<!-- If you go to http://host/project/ (with no file name), it will
try index.jsf first, welcome.jsf next, and so forth.
-->
<welcome-file-list>
<welcome-file>enternameform.jsf</welcome-file>
<welcome-file>welcome.jsf</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Please let me know what I may be doing wrong here.
It has been fixed after restarting server n some edits
I'm trying to use Bean validation instead of JSF validation since it is a more DRY aproach, i'm using the annotations on my model but when i insert null data on jsf fields it does nothing...
None of the annotations that i'm using is having any effect, its like they are not there....
I'm using Tomcat 8
My xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</h:head>
<h:body>
<h1>Cadastro de funcionario</h1>
<h:form>
<h:messages/>
<h:panelGrid columns="3">
<h:outputLabel value="Salário: R$ " for="campo-salario"/>
<h:inputText id="campo-salario" value="#{funcionarioBean.funcionario.salario}">
<f:convertNumber locale="pt_BR"/>
</h:inputText>
<h:message for="campo-salario" />
<h:outputLabel value="Código: " for="campo-codigo"/>
<h:inputText id="campo-codigo" value="#{funcionarioBean.funcionario.codigo}"/>
<h:message for="campo-codigo"/>
<h:outputLabel value="Data: " for="campo-aniversario"/>
<h:inputText id="campo-aniversario" value="#{funcionarioBean.funcionario.aniversario}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
<h:message for="campo-aniversario"/>
<h:commandButton value="Cadastrar" action="#{funcionarioBean.mensagem}"/>
</h:panelGrid>
</h:form>
</h:body>
</html>
My Bean
#ManagedBean
public class FuncionarioBean {
private Funcionario funcionario = new Funcionario();
public void mensagem(){
System.out.println("Pressionado");
}
public Funcionario getFuncionario() {
return funcionario;
}
public void setFuncionario(Funcionario funcionario) {
this.funcionario = funcionario;
}
}
My Funcionario class
import java.util.Date;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class Funcionario {
#NotNull(message="{br.com.k19.Funcionario.nome")
#Min(value = 0)
private Double salario;
#NotNull
#Min(value = 5)
#Max(value = 19)
private Integer codigo;
#NotNull
private Date aniversario;
public Double getSalario() {
return salario;
}
public void setSalario(Double salario) {
this.salario = salario;
}
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public Date getAniversario() {
return aniversario;
}
public void setAniversario(Date aniversario) {
this.aniversario = aniversario;
}
}
My lib
Can't post pictures yet.
Lib
>
antlr-2.7.7.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-4.0.5.Final.jar
hibernate-core-4.3.6.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
hibernate-validator-5.0.0.final.jar
jandex-1.1.0.Final.jar
javassist-3.18.1-GA.jar
javax.servlet.jsp.jstl-1.2.1.jar
javax.servlet.jsp.jstl-api-1.2.1.jar
jboss-logging-3.1.3.GA.jar
jboss-logging-annotations-1.2.0.Beta1.jar
jboss-transaction-api_1.2_spec-1.0.0.Final.jar
jsf-api-2.2.8.jar
jsf-impl-2.2.8.jar
mysql-connector-java-5.1.23.bin.jar
omnifaces-1.8.1.jar
primefaces-5.0.jar
validation-api-1.0.0.GA.jar
My web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>K19-Conversao-e-Validacao</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>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>com.sun.faces.writeStateAtFormEnd</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
Downloaded hibernate jars again to match the versions
Download validator: http://hibernate.org/validator/
Download ORM: http://hibernate.org/orm/
My lib
Working as intend now
ref: Bean Validation #NotNull, #NotBlank and #NotEmpty does not work in JSF+Tomcat
Objective: Want to retrieve and store the user related info (over 5 columns in USER table) in the session when user is authenticated, so that I can use the user info at various point in time during the current session.
Approach: I have chosen to do this by using a managed Bean (LoginBean.java) for authentication in my JavaServerFaces application. I would retrieve the user info and store them in the session in the LoginBean.login() method.
Ref: http://docs.oracle.com/javaee/6/tutorial/doc/glxce.html#glxef
Bean Code:
#ManagedBean
#SessionScoped
public class LoginBean {
private String id;
private String password;
public LoginBean() {
System.out.println("LoginBean() called .....");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String login() {
System.out.println("login() invoked .....");
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();
try {
request.login(id, password);
} catch (ServletException e) {
facesContext.addMessage(null, new FacesMessage("Login failed."));
return "error";
}
return "home";
}
public void logout() {
System.out.println("logout() invoked .....");
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();
try {
request.logout();
} catch (ServletException e) {
facesContext.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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>AuthenticationUsingLoginBean</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>*.xhtml</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>jdbcRealm</realm-name>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/error.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources are restricted</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>
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 xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Form based authentication with login bean</title>
</h:head>
<h:body>
<h:form>
<h:outputLabel for="usernameInput">User ID:</h:outputLabel>
<h:inputText id="usernameInput" value="#{loginBean.id}" required="true" />
<h:message for="usernameInput"/>
<br />
<h:outputLabel for="passwordInput">Password:</h:outputLabel>
<h:inputSecret id="passwordInput" value="#{loginBean.password}" required="true" />
<h:message for="passwordInput" />
<br />
<h:commandButton value="Login" action="#{loginBean.login}" />
</h:form>
</h:body>
</html>
Issue
I've started new browser window and accessed the home page (home.xhml).
I am redirected to login.xhtml, which is fine.
But, on clicking Login button on login.xhtml UI, LoginBean.login() method is NOT getting invoked.
Note
login.xhtml should be correct as LoginBean.login() method is invoked successfully when I comment out <login-config> in web.xml file. Obviously, I can't keep it commented as the authentication won't work as expected.
Update
I have the necessary JDBCRealm configured in my tomcat's server.xml file and made sure that it works fine by implementing a sample form based authentication using j_security_check.
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost/xyz"
connectionName="root"
connectionPassword="xxxxx"
userTable="USER" userCredCol="PASSWORD"
userRoleTable="USER_ROLE_MPNG" userNameCol="ID" roleNameCol="ROLE_NAME" />
Software used:
apache-tomcat-7.0.47
JSF 2.1 (Mojarra 2.1.6)
<h:commandButton value="Login" action="#{loginBean.login()}" />
mind the () after login. you're calling a methode not trying to getter/setter a var with the name login in LoginBean.
The reason this is not working is because you are restricting all resources in your web.xml. You can see your login and error pages, but that does not mean that everything surrounding it is accessible, on the contrary.
Solution
Add a new security constraint for public resources, like this:
<security-constraint>
<web-resource-collection>
<web-resource-name>Open Resources</web-resource-name>
<url-pattern>/public/*</url-pattern>
</web-resource-collection>
</security-constraint>
Now, create a new sub-folder where your login.xhtml and error.xhtml are and call it public, as in the security constraint. Move your login.xhtml and error.xhtml into the newly created folder and adjust the login configuration in your web.xml accordingly.
A question about JSF 2 implicit navigation. He seeks only page in the root directory? Because I separate my pages in folders on WebContent except index.php page that I let inside the WebContent. My application service begins normally opens the index page that contains a button to the login page, the login page is in a directory called "public" which is inside the WebContent directory. When I click the button on the index page shows that he could not find the login page.
I've tried to change the result of the method of the ManagedBean that directs you to the login page, looked like this: "public / login.xhtml", but neither worked.
I thank anyone who can help me.
EDIT
ManagedBean
package financeiro.web;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import financeiro.usuario.Usuario;
import financeiro.usuario.UsuarioRN;
#ManagedBean(name = "usuarioBean")
#RequestScoped
public class UsuarioBean {
private Usuario usuario;
private String confirmarSenha;
public UsuarioBean() {
}
public String novo() {
this.usuario = new Usuario();
this.usuario.setAtivo(true);
/*
* Solution according to the Xtreme Biker. Works now. Thanks.
* Before: public/usuario
* After: /public/usuario
*/
return "/publico/usuario";
}
public String salvar() {
FacesContext context = FacesContext.getCurrentInstance();
String senha = this.usuario.getSenha();
if (!senha.equals(this.confirmarSenha)) {
FacesMessage facesMessage = new FacesMessage(
"A senha não foi confirmada corretamente.");
context.addMessage(null, facesMessage);
return null;
}
UsuarioRN usuarioRN = new UsuarioRN();
usuarioRN.salvar(usuario);
return "usuarioSucesso";
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public String getConfirmarSenha() {
return confirmarSenha;
}
public void setConfirmarSenha(String confirmarSenha) {
this.confirmarSenha = confirmarSenha;
}
}
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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>FinanceiroWeb</display-name>
<servlet>
<display-name>Faces Servlet</display-name>
<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>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<filter>
<filter-name>conexaoFilter</filter-name>
<filter-class>financeiro.web.filter.ConexaoHibernateFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>conexaoFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
index.html
<meta http-equiv="Refresh" content="0;URL=publico/login.xhtml" />
login.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Login</title>
</h:head>
<h:body>
<h1>Login</h1>
<hr />
<h:form>
<h:commandButton action="#{usuarioBean.novo}" value="Registre-se" />
</h:form>
<hr />
</h:body>
</html>
Directory structure of the project
OBS.: I use Maven Project
Link image: http://postimg.org/image/bm7iwbmxf/
I was trying to create a secure login page with jsf, and I used these code snippets as the solution, found in this question. My problem is, that I can access the /restricted/secret.xhtml without logging in, there is no redirect it's like the filter is not applied, because if I go directly to the /restricted/secret.xhtml the #{user.loggedIn} evaluates to false and I still can view the page. Here is my code:
AuthFilter.java
public class AuthFilter implements Filter {
private FilterConfig config;
#Override
public void destroy() {
this.config = null;
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain ch) throws IOException, ServletException {
HttpSession s = ((HttpServletRequest) req).getSession();
if (s.getAttribute(UserBean.CREDENTIAL)==null)
{
((HttpServletResponse) resp).sendRedirect("/login.faces");
}else
{
ch.doFilter(req, resp);
}
}
#Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}
UserBean.java
#ManagedBean(name="user")
#SessionScoped
public class UserBean implements Serializable {
private String name;
private String password;
protected static final String CREDENTIAL = "ontherun";
private static final long serialVersionUID = 1L;
public String getName()
{
return this.name;
}
public void setName(String newName)
{
this.name = newName;
}
public String getPassword()
{
return this.password;
}
public void setPassword(String newPassword)
{
this.password = newPassword;
}
public boolean isLoggedIn()
{
return FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get(CREDENTIAL) != null;
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(CREDENTIAL);
return null;
}
public String login()
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(CREDENTIAL, this.name);
return "secret";
}
}
Here is my login.xhtml ; the page works correctly, so there is no problem with the template file.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<head><title>IGNORED</title></head>
<body>
<ui:composition template="/templates/masterLayoutTemplate.xhtml">
<ui:define name="windowTitle">
#{msgs.window_title}
</ui:define>
<ui:define name="header">
<ui:include src="/sections/login/header.xhtml"></ui:include>
</ui:define>
<ui:define name="footer">
<ui:include src="/sections/login/footer.xhtml"></ui:include>
</ui:define>
<ui:define name="content">
<h:form>
<h:panelGrid columns="2">
#{msgs.namePrompt}
<h:inputText id="name" value="#{user.name}"/>
#{msgs.passwordPrompt}
<h:inputSecret id="password" value="#{user.password}"/>
</h:panelGrid>
<p>
<h:commandButton value="#{msgs.loginButtonText}" action="#{user.login }"/>
</p>
<p>
You are logged in : #{user.loggedIn}
</p>
<p>
<h:commandButton value="logout" action="#{user.logout }"/>
</p>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
Here is the secret.xhtml which is supposed to be restricted:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<head><title>IGNORED</title></head>
<body>
<ui:composition template="/templates/masterLayoutTemplate.xhtml">
<ui:define name="windowTitle">
#{msgs.window_title}
</ui:define>
<ui:define name="content">
<h:head></h:head>
<h:body>
<p>You are #{user.loggedIn}</p>
</h:body>
</ui:define>
</ui:composition>
</body>
</html>
And here are my config files: 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" version="3.0">
<display-name>OnTheRun</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>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>on.run.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/restricted/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
</web-app>
and 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">
<application>
<resource-bundle>
<base-name>on.run.messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/profile.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>secret</from-outcome>
<to-view-id>/restricted/secret.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
</faces-config>
My directory structure looks like this: dirStruct 2
You've mapped FacesServlet on /faces/* instead of *.xhtml. So all JSF requests will have the /faces prefix in the URL. But you've mapped the AuthFilter on /restricted/* instead of /faces/restricted/*, so it will never kick in on /faces/* URLs.
You can solve this in 2 ways:
Map FacesServlet on *.xhtml instead of on /faces/*. This has the additional advantage that the enduser won't ever be able to see the raw JSF source code when the enduser purposefully removes the /faces path from the URL in browser address bar.
Map AuthFilter on /faces/restricted/* instead of on /restricted/*.
I personally recommend the first way. You end up with a shorter and nicer URL and you immediately also prevent the JSF source code leak.