JSF过滤器在初始重定向后不重定向[关闭]
Posted
技术标签:
【中文标题】JSF过滤器在初始重定向后不重定向[关闭]【英文标题】:JSF Filter not redirecting After Initial Redirect [closed] 【发布时间】:2012-11-02 05:56:21 【问题描述】:我正在尝试设置网络过滤器并需要一些帮助。我的过滤器在初始登录时工作正常,但是当会话超时并且我单击任何链接时,它会触发我的重定向语句,但浏览器中的网页永远不会被重定向。任何人都可以帮助解决这个问题吗?非常感谢。
过滤器
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package src;
import java.io.IOException;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
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;
import javax.servlet.http.HttpSession;
/**
*
* @author Bernard
*/
@WebFilter(filterName = "LoginFilter", urlPatterns = "/*")
public class LoginFilter implements Filter
//FilterConfig fc;
@Override
public void init(FilterConfig filterConfig) throws ServletException
//fc = filterConfig;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession(true);
String pageRequested = req.getRequestURL().toString();
Boolean authenticated = (Boolean) session.getAttribute("authenticated");
if (authenticated == null)
authenticated = false;
if (!authenticated && !pageRequested.contains("login"))
res.setStatus(301);
res.sendRedirect(req.getContextPath() + "/login/login.xhtml");
else
chain.doFilter(request, response);
@Override
public void destroy()
//fc = null;
Faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<!-- =========== FULL CONFIGURATION FILE ================================== -->
<faces-config version="2.1"
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_1.xsd">
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/login/login.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
</faces-config>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>/index.xhtml</welcome-file>
</welcome-file-list>
<filter>
<filter-name>restrict</filter-name>
<filter-class>src.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>restrict</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
验证 Bean
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package src;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
*
* @author Bernard
*/
@ManagedBean
@SessionScoped
public class Authenticator
private String username;
private String password;
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 String authenticateUser(ServletRequest request)
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession(true);
session.setMaxInactiveInterval(30);
Boolean authenticated = (Boolean) session.getAttribute("authenticated");
Database pgDatabase = new Database();
Admin foundAdmin = null;
try
foundAdmin = (Admin) pgDatabase.findAdminByUsername(username);
catch (ClassNotFoundException ex)
Logger.getLogger(Authenticator.class.getName()).log(Level.SEVERE, null, ex);
Admin currentAdmin = new Admin();
currentAdmin.userName = username;
currentAdmin.password = this.hashPassword((password));
if (authenticated != null && authenticated != true)
if (foundAdmin != null)
if (currentAdmin.equals(foundAdmin))
authenticated = true;
session.setAttribute("authenticated", true);
return "success";
else
authenticated = false;
session.setAttribute("authenticated", false);
return "failure";
else
authenticated = false;
session.setAttribute("authenticated", false);
return "failure";
else
session.setAttribute("authenticated", true);
authenticated = true;
return "success";
public String logOut()
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extCtx = ctx.getExternalContext();
Map<String, Object> sessionMap = extCtx.getSessionMap();
sessionMap.put("authenticated", false);
return "failure";
public String hashPassword(String passwordToHash)
String hashword = null;
try
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(password.getBytes());
BigInteger hash = new BigInteger(1, md5.digest());
hashword = hash.toString(16);
catch (NoSuchAlgorithmException nsae)
return hashword;
【问题讨论】:
您的日志文件中是否出现 ViewExpiredException? 如果没有人回答,我会在几个小时内详细阅读它 我也有同样的问题。以下解决方案工作正常。 【参考方案1】:您的过滤器看起来不错(除了非常弱的 url.contains("login")
测试和两种方式错误地将响应状态设置为 301 以及检查登录用户的方式有点差)。
我认为您的具体问题是由于您通过 ajax 链接而不是普通链接执行导航。您不能以这种方式在 ajax 响应上发送重定向。 JSF ajax 引擎和 webbrowser 都不遵循 JSF ajax 响应的 302 重定向。客户端最终得到一个完全被忽略的 ajax 响应。
相反,您应该发送一个特殊的 XML 响应,指示 JSF ajax 引擎发送重定向。这正是在 JSF 上下文中发送的 XML 响应,ExternalContext#redirect()
在 ajax 请求期间被使用。
<?xml version="1.0" encoding="UTF-8"?>
<partial-response>
<redirect url="/contextpath/login/login.xhtml"></redirect>
</partial-response>
在 servlet 过滤器中,您应该首先检查请求是否涉及 JSF ajax 请求,如果是,则返回上述 XML 响应,否则只需按通常的方式调用 HttpServletResponse#sendRedirect()
。您可以通过检查 Faces-Request
请求标头是否存在并且等于 partial/ajax
来做到这一点。
if ("partial/ajax".equals(request.getHeader("Faces-Request")))
// It's a JSF ajax request.
总而言之,您的doFilter()
现在应该是这样的:
String loginURL = req.getContextPath() + "/login/login.xhtml";
if (!authenticated && !req.getRequestURI().equals(loginURL))
if ("partial/ajax".equals(request.getHeader("Faces-Request")))
res.setContentType("text/xml");
res.getWriter()
.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
else
res.sendRedirect(loginURL);
else
chain.doFilter(request, response);
【讨论】:
BallusC,非常感谢。这似乎工作得很好。这是我第一次尝试 Java 应用程序以及整体编码,所以我不太热衷于做事的最佳实践。如果您能以任何方式改进我的用户检查方法,我将不胜感激。无论哪种方式,我都非常感谢您的帮助。 不客气。至于登录检查,不要在会话范围内存储布尔值。存储User
本身。这样您就可以直接访问其信息,例如用户名、电子邮件、角色等,而无需每次都请求。在过滤器中,只需检查session.getAttribute("user") != null
。
知道了。再次非常感谢。
感谢这个解决方案,我也遇到了同样的问题。以上是关于JSF过滤器在初始重定向后不重定向[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在 servlet 过滤器中使用请求参数将 JSF ajax 请求重定向到 URL
JSF 2 + Spring 3 + Shiro - 会话超时不重定向到登录页面