0

我为我的 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>

4

2 回答 2

1

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

您需要从身份验证检查中排除 JSF 资源。您可以通过检查请求 URI 是否在 webapp 上下文路径ResourceHandler.RESOURCE_IDENTIFIER(其值为/javax.faces.resource)之后开始来做到这一点。

所以,基本上:

HttpServletRequest req = (HttpServletRequest) request;

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

检查文件扩展名很笨拙,并且不足以涵盖所有可能的资源请求。

于 2012-11-18T23:16:20.040 回答
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.
            }
        }
    } 
于 2012-11-18T13:07:52.063 回答