JSF h:commandLink无法使用过滤器

时间:2012-11-18 12:50:06

标签: jsf-2 servlet-filters

我为jsf项目创建了简单的登录系统。 在项目中,我创建过滤器以检查用户登录状态。

  • 如果登录,请继续请求页面。

  • 如果没有登录或会话被破坏,请重定向到登录页面

我的问题是,如果我应用过滤器,则所有h:commandLink在单击后都不会处理任何内容。但是当我删除过滤器时,一切都运行良好。

我尝试将h:commandButton与fileter一起使用,然后正常工作。

我该如何解决这个问题? 我研究了很长时间,但没有找到任何解决方案。 请帮帮我!

过滤代码:

    @WebFilter(filterName = "AuthenticationFilter", urlPatterns = {"*.htm"}, dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
public class AuthenticationFilter implements Filter {

    // The filter configuration object we are associated with.  If
    // this value is null, this filter instance is not currently
    // configured. 
    private FilterConfig filterConfig = null;

    @Inject
    private AuthenticationManager authenticationManager;  

    public AuthenticationFilter() {
    } 

    /**
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

        Throwable problem = null;        
        try {
            HttpServletRequest req = (HttpServletRequest) request; 
            String requestUrl = req.getRequestURI(); 

            String contextPath = req.getContextPath(); 
            if(contextPath.equals("/")){
                contextPath = "";
            }
            String jsfUrl = requestUrl.replaceFirst(contextPath, "");

            if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
                chain.doFilter(request, response);                
            } 
            else {
                String redirectPath = contextPath+"/login.htm";
                ((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
            }
        } 
        catch (Throwable t) {
            // If an exception is thrown somewhere down the filter chain,
            // we still want to execute our after processing, and then
            // rethrow the problem after that.
            problem = t;
        }

        // If there was a problem, we want to rethrow it if it is
        // a known type, otherwise log it.
        if (problem != null) {
            if (problem instanceof ServletException) {
                throw (ServletException) problem;
            }
            if (problem instanceof IOException) {
                throw (IOException) problem;
            }
            sendProcessingError(problem, response);
        }
    }

    /**
     * Return the filter configuration object for this filter.
     */
    public FilterConfig getFilterConfig() {
        return (this.filterConfig);
    }

    /**
     * Set the filter configuration object for this filter.
     *
     * @param filterConfig The filter configuration object
     */
    public void setFilterConfig(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy() {        
    }

    @Override
    public void init(FilterConfig filterConfig) {        
        this.filterConfig = filterConfig;
        if (filterConfig != null) {
        }
    }
}

Jsf代码:

<h:body>
<f:view contentType="text/html" locale="#{authenticationManager.languageCode}">
<div class="header">
    <h:form id="topForm" prependId="false">
        <div class="logo">
            <h1><img src="#{facesContext.externalContext.requestContextPath}/resources/images/login-logo2.png" width="220" height="64"/></h1>
        </div>  
        <ul class="navTop">
            <li>
                <a href="#"><span class="pictograms">f</span>#{authenticationManager.currentUser.firstName} #{authenticationManager.currentUser.lastName}</a>
            </li>
            <li>
                <a href="#"><span class="pictograms">m</span>Messages</a>
            </li>
            <li class="logout">
                <h:commandButton action="#{authenticationManager.logout()}" value="aaaaaaa" style="color:#fff;" />
                <h:commandLink action="#{authenticationManager.logout()}" value="#{label.Logout}"/>
                <h:commandLink immediate="true" action="#{authenticationManager.logout}" id="logoutLink">
                    <span class="pictograms">E</span>***This link is not work correctly***
                </h:commandLink>
            </li>
        </ul>           
        <ui:insert name="mainmenu"/>
    </h:form>
</div>

2 个答案:

答案 0 :(得分:1)

导致您的具体问题,因为过滤器阻止了JSF默认资源jsf.js的服务。此资源对于JSF命令链接和JSF ajax请求的运行是必需的(没有ajax的普通命令按钮才能正常工作)。

您需要从身份验证检查中排除JSF资源。您可以通过检查请求URI是否在具有ResourceHandler.RESOURCE_IDENTIFIER(值为/javax.faces.resource)的webapp上下文路径之后开始执行此操作。

所以,基本上:

HttpServletRequest req = (HttpServletRequest) request;

if (req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
    chain.doFilter(request, response); // Let it continue.
    return;
}

检查文件扩展名是笨拙的,并没有充分涵盖所有可能的资源请求。

答案 1 :(得分:0)

经过研究,我没有找到任何解决方案。 所以我采取了许多可能的方式,并找到了解释。

我使用过滤模式“* .htm”过滤所有内容,然后每个请求(如.js.htm,.css.htm,.gif.htm,.jpg.htm)都会重定向到login.htm页面。

重点是将.js.htm重定向到登录页面而不是右侧文件。 所以像jsf.js.htm这样的重要库被重定向到login.htm,这是使h:commandLink工作不正确的主要原因。

跳这会帮助像我这样的人。

try {
        HttpServletRequest req = (HttpServletRequest) request; 
        String requestUrl = req.getRequestURI(); 

        if(requestUrl.endsWith(".js.htm") 
            || requestUrl.endsWith(".css.htm") 
            || requestUrl.endsWith(".gif.htm") 
            || requestUrl.endsWith(".png.htm") 
            || requestUrl.endsWith(".jpg.htm") 
            || requestUrl.endsWith(".jpeg.htm")){
            chain.doFilter(request, response);            
        }
        else{
            String contextPath = req.getContextPath(); 
            if(contextPath.equals("/")){
                contextPath = "";
            }
            String jsfUrl = requestUrl.replaceFirst(contextPath, "");

            if (authenticationManager.allowedAccess(jsfUrl) || requestUrl.equalsIgnoreCase(contextPath+"/login.htm")) {
                chain.doFilter(request, response);                
            } 
            else {
                String redirectPath = contextPath+"/login.htm";
                ((HttpServletResponse) response).sendRedirect(redirectPath); // Not logged in, so redirect to error page.
            }
        }
    }