[英]Infinite loop when trying to login using Servlet Filter in JSF
I am trying to create a login application using JSF and servlet filter, but when user logs in nothing happens. 我正在尝试使用JSF和servlet过滤器创建登录应用程序,但是当用户登录时什么也没发生。 It redirects to login page again.
它再次重定向到登录页面。
Here is the project directory: 这是项目目录:
Here is web.xml 这是web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>javaeetutorial.guessnumber.filters.LoggedInFilter</filter-class>
</filter>
<!-- Set the login filter to secure all the pages in the /secured/* path of the application -->
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/secured/*</url-pattern>
</filter-mapping>
<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>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>greeting.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Here is LoggedInFilter.java 这是LoggedInFilter.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaeetutorial.guessnumber.filters;
import java.io.IOException;
import java.util.Enumeration;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javaeetutorial.guessnumber.TestBean;
/**
*
* @author salih
*/
public class LoggedInFilter implements Filter {
FilterConfig fc;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
fc = filterConfig;
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Enumeration<String> t = ((HttpServletRequest) request).getSession().getAttributeNames();
while(t.hasMoreElements()) { System.out.println(t.nextElement().toString());}
TestBean loginBean = (TestBean) ((HttpServletRequest) request).getSession().getAttribute("testBean");
// For the first application request there is no loginBean in the session so user needs to log in
// For other requests loginBean is present but we need to check if user has logged in successfully
if (loginBean == null || !loginBean.isLoggedIn()) {
String contextPath = ((HttpServletRequest) request).getContextPath();
((HttpServletResponse) response).sendRedirect(contextPath + "/login.xhtml");
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
Here is TestBean.java 这是TestBean.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaeetutorial.guessnumber;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.context.FacesContext;
import javax.inject.Named;
/**
*
* @author salih
*/
@Named
@SessionScoped
public class TestBean implements Serializable {
private boolean loggedIn;
private String username;
private String password;
private NavigationBean navigationBean = new NavigationBean();
private static final String[] users = {"anna:qazwsx", "kate:123456"};
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public String doLogin() {
// Get every user from our sample database :)
for (String user : users) {
String dbUsername = user.split(":")[0];
String dbPassword = user.split(":")[1];
// Successful login
if (dbUsername.equals(username) && dbPassword.equals(password)) {
loggedIn = true;
return navigationBean.redirectToWelcome();
}
}
// Set login ERROR
FacesMessage msg = new FacesMessage("Login error!", "ERROR MSG");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext.getCurrentInstance().addMessage(null, msg);
// To to login page
return navigationBean.toLogin();
}
}
Here is login.xhtml 这是login.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"htth://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Login form</title>
</h:head>
<h:body>
<h3>Login here</h3>
<h:form id="login-form">
<h:outputText value="username:"/>
<h:inputText value="#{testBean.username}" id="username"/>
<br/>
<h:outputText value="password:"/>
<h:inputSecret value="#{testBean.password}" id="password"/>
<br/>
<h:commandButton id="button" value="Login" action="#{testBean.doLogin}"/>
<br/>
<h:commandLink action="#{navigationBean.redirectToInfo}" value="Info page"/>
<br/>
<h:messages />
<br/>
</h:form>
</h:body>
</html>
You are mixing JSF managed beans / concepts with CDI managed beans. 您正在将JSF托管Bean /概念与CDI托管Bean混合使用。
First off you neglected to specify your container but I will write one answer for plain servlet container and one for a CDI enabled java application server such as TomEE / Wildfly / Glassfish. 首先,您忽略了要指定的容器,但是我将为普通的servlet容器写一个答案,为启用CDI的Java应用程序服务器(例如TomEE / Wildfly / Glassfish)写一个答案。
Use @Named
and @SessionScoped
but make sure you have the correct @SessionScoped. 使用
@Named
和@SessionScoped
但请确保您具有正确的@SessionScoped。 javax.enterprise.context is the package name. javax.enterprise.context是程序包名称。 If you use the SessionScoped from JSF the bean will be dependent scoped and that's wrong.
如果您使用JSF中的SessionScoped,则bean将具有依赖范围,这是错误的。
Now remove the filter and do a quick test with a test page. 现在,卸下过滤器并使用测试页进行快速测试。 Set a field with
<h:inputText />
and <h:commandButton>
(both in a <h:form>
). 使用
<h:inputText />
和<h:commandButton>
(均在<h:form>
)设置一个字段。 Make sure the value is still there after F5 and thus sucessfully @SessionScoped.
确保F5之后的值仍然存在,并因此成功
@SessionScoped.
If it does not work makes sure you are using CDI 1.1 or that you have beans.xml present accordingly to docs. 如果它不起作用,请确保您正在使用CDI 1.1或已在文档中相应地包含beans.xml。
Lastly use 最后使用
@Inject
private TestBean testBean;
Or if you have a plain container like Tomcat or Jetty you need to use Deltaspike Core and then: TestBean testBean = BeanProvider.getContextualReference(TestBean.class, false);
或者,如果您拥有像Tomcat或Jetty这样的普通容器,则需要使用Deltaspike Core,然后使用:
TestBean testBean = BeanProvider.getContextualReference(TestBean.class, false);
good luck 祝好运
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.