jsf过滤器似乎不起作用

Posted

技术标签:

【中文标题】jsf过滤器似乎不起作用【英文标题】:jsf filter seems not to work 【发布时间】:2012-06-11 15:38:28 【问题描述】:

我试图用 jsf 创建一个安全的登录页面,我使用这些代码 sn-ps 作为解决方案,在 this question 中找到。我的问题是,我可以在不登录的情况下访问/restricted/secret.xhtml,没有重定向,就像没有应用过滤器一样,因为如果我直接进入/restricted/secret.xhtml #user.loggedIn 评估为假,我仍然可以查看该页面。这是我的代码:

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";


这是我的 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: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>

这是应该被限制的secret.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: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>

这是我的配置文件: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>

和 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>

我的目录结构如下:dirStruct2

【问题讨论】:

【参考方案1】:

您已将FacesServlet 映射到/faces/* 而不是*.xhtml。所以所有 JSF 请求都将在 URL 中具有 /faces 前缀。但是您已将AuthFilter 映射到/restricted/* 而不是/faces/restricted/*,因此它永远不会启动/faces/* URL。

您可以通过两种方式解决此问题:

    FacesServlet 映射到*.xhtml 而不是/faces/*。这还有一个额外的好处,即当最终用户故意从浏览器地址栏中的 URL 中删除 /faces 路径时,最终用户将永远无法看到原始 JSF 源代码。

    AuthFilter 映射到/faces/restricted/* 而不是/restricted/*

我个人推荐第一种方式。您最终会得到一个更短更好的 URL,并且您还可以立即防止 JSF 源代码泄漏。

【讨论】:

感谢您的帮助。我还必须在过滤器中修改“../login.xhtml”的重定向路径。有没有更优雅的方法来做到这一点>我的意思是如何设置我的路径来加载项目目录?在我的情况下,如果我只写 login.xhtml 或 /login.xhtml,它会重定向到 localhost/login.xhtml,而不是 localhost/ProjectName/login.xhtml。 使用String loginURL = request.getContextPath() + "/login.xhtml";

以上是关于jsf过滤器似乎不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Shiro URL 过滤器不起作用

通过 Ajax 更新 JSF 组件后,JavaScript/jQuery 事件侦听器不起作用

JSF 页面中的 <c:choose><c:when> 不起作用,似乎总是评估为 false

JSF 2.2 将提交的空字符串值解释为 null 不起作用

富:列的 f:facet 中的 outputText 和 inputText 不起作用 - JSF

Bean Validation @NotNull、@NotBlank 和 @NotEmpty 在 JSF+Tomcat 中不起作用