在Servlet过滤器中访问FacesContext的问题

时间:2014-02-20 06:16:52

标签: jsf-2 tomcat6 servlet-filters

我想在Servlet过滤器中访问FacesContext, 有时(不是每次)我都会遇到内部服务器错误。

AuthenticationFilter.java

import java.io.IOException;

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.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;


public class AuthenticationFilter implements Filter {
    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        request.setCharacterEncoding("UTF-8");
        UserDetailsBean userBean = null;
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse res = (HttpServletResponse)response; 
        FacesContext context = FacesUtil.getFacesContext(req, res);
        String param = req.getParameter("PARAMETER_VALUES");

        if((param!=null && param.isEmpty()) || !isAuthenticated(req)) {

            if(param != null && !param.isEmpty()) {
                userBean = new UserDetailsBean();
                setCookies(param, userBean, req, res);
                FacesUtil.setManagedBeanInView(context, "userDetailsBean", userBean);
                request.setAttribute("userDetailsBean", userBean);
                chain.doFilter(request, response);
            }
            else {
                String homePage = "http://homePage";
                res.sendRedirect(homePage);
            }
        }
        else {
            try {
                if(!context.isPostback()){
                    userBean = getUserBeanFromCookies(req.getCookies());
                    request.setAttribute("userDetailsBean", userBean);
                }
            } catch(Exception e) {
                userBean = getUserBeanFromCookies(req.getCookies());
                request.setAttribute("userDetailsBean", userBean);
            }

            chain.doFilter(request, response);
        }
    }

    private UserDetailsBean getUserBeanFromCookies(Cookie[] cookies) {
        UserDetailsBean userBean = new UserDetailsBean();
        for(Cookie c: cookies) {
            String cName = c.getName();
            if("userId".equals(cName)) {
                userBean.setUserNbr(c.getValue());
            }
            else if("userEmail".equals(cName)) {
                userBean.setEmail(c.getValue());
            }
            else if("firstName".equals(cName)) {
                userBean.setFirstName(c.getValue());
            }
            else if("lastName".equals(cName)) {
                userBean.setLastName(c.getValue());
            }
        }

        return userBean;
    }

    private boolean setCookies(String param, UserDetailsBean userBean, HttpServletRequest request, HttpServletResponse response) {
        boolean validUser = false;
        if(param != null) {
            String strParams = new String(Base64.decodeBase64(param.getBytes()));
            String[] pairs = strParams.split("&");
            for(String pp: pairs) {
                String[] s = pp.split("=");
                if("p_userid".equals(s[0])) {
                    userBean.setUserNbr(s[1]);
                    validUser = true;
                }
                else if("p_email".equals(s[0])){
                    userBean.setEmail(s[1]);
                }
                else if("p_first_name".equals(s[0])) {
                    userBean.setFirstName(s[1]);
                }
                else if("p_last_name".equals(s[0])) {
                    userBean.setLastName(s[1]);
                }
            }
        }

        if(validUser) {
            String cookiePath = "/";

            Cookie cookie = new Cookie("userId", userBean.getUserNbr());
            cookie.setMaxAge(-1); // Expire time. -1 = by end of current session, 0 = immediately expire it, otherwise just the lifetime in seconds.
            cookie.setPath(cookiePath);
            response.addCookie(cookie);
            cookie = new Cookie("userEmail", userBean.getEmail());
            cookie.setMaxAge(-1);
            cookie.setPath(cookiePath);
            response.addCookie(cookie);
            cookie = new Cookie("firstName",userBean.getFirstName());
            cookie.setMaxAge(-1);
            cookie.setPath(cookiePath);
            response.addCookie(cookie);
            cookie = new Cookie("lastName", userBean.getLastName());
            cookie.setMaxAge(-1);
            cookie.setPath(cookiePath);
            response.addCookie(cookie);
        }
        return validUser;
    }

    public boolean isAuthenticated(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if(cookies == null) {
            return false;
        }

        for(Cookie c: cookies) {
            String cName = c.getName();
            if("userId".equals(cName)) {
                if(c.getValue() == null || c.getValue().isEmpty()) {
                    return false;
                }
                else {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }
}

UserDetailsBean.java

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ViewScoped    
@ManagedBean(name="userDetailsBean")
public class UserDetailsBean implements Serializable {

    private String userNbr;
    private String email;
    private String firstName;
    private String lastName;

    public String getUserNbr() {
        return userNbr;
    }
    public void setUserNbr(String userNbr) {
        this.userNbr = userNbr;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

FacesUtil.java

import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FacesUtil {

      public static FacesContext getFacesContext(HttpServletRequest request, HttpServletResponse response) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext == null) {
          LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
          Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
          FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
          facesContext = contextFactory.getFacesContext(request.getSession().getServletContext(), request, response, lifecycle);
          UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "");
          facesContext.setViewRoot(view);
          FacesContextWrapper.setCurrentInstance(facesContext);
        }
        return facesContext;
      }


      // Wrap the protected FacesContext.setCurrentInstance() in a inner class.
      private static abstract class FacesContextWrapper extends FacesContext {
        protected static void setCurrentInstance(FacesContext facesContext) {
          FacesContext.setCurrentInstance(facesContext);
        }
      }
}

这里的身份验证实际上是由其他应用程序处理的, 一旦用户登录,它将发送带有一些信息的请求参数(PARAMETER_VALUES)。

我们正在使用JSF 2.1.9& Tomcat 6.0.35。 我在Filter的这一行收到错误 FacesContext context = FacesUtil.getFacesContext(req,res);

错误堆栈跟踪:

Exception=java.lang.NullPointerException
        at org.apache.catalina.connector.Request.parseParameters(Request.java:2599)
        at org.apache.catalina.connector.Request.getParameter(Request.java:1106)
        at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:355)
        at javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:158)
        at com.sun.faces.context.RequestParameterMap.containsKey(RequestParameterMap.java:99)
        at java.util.Collections$UnmodifiableMap.containsKey(Collections.java:1280)
        at com.sun.faces.renderkit.ResponseStateManagerImpl.isPostback(ResponseStateManagerImpl.java:84)
        at com.sun.faces.context.FacesContextImpl.isPostback(FacesContextImpl.java:207)
        at com.sandbox.external.site.test.filter.AuthenticationFilter.doFilter(AuthenticationFilter.java:36)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.ha.tcp.ReplicationValve.invoke(ReplicationValve.java:347)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:396)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)

当我在错误说明的行中看到Tomcat 6.0.35的源代码时,     if(!getMethod()。equalsIgnoreCase(“POST”))         返回; 在这里找不到太多信息。

1 个答案:

答案 0 :(得分:5)

您无法访问过滤器中的FacesContext,因为FacesContext已初始化FacesServlet,并且在请求到达servlet之前会处理您的过滤器。

如果它有时有效,可能是因为副作用(JSF为每个请求创建一个FacesContext,每个请求都绑定到一个线程,并且线程被servlet容器重用)。

我也想知道你为什么要通过实施自己的安全过滤器来重新发明轮子。已有的解决方案可用(如Spring Security或标准JEE security)并经过充分测试。

有关BalusC的更多信息,请参阅此问题: