문제

I am trying to access FacesContext in Servlet Filter, And sometimes (not everytime) i encounter internal server errors.

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);
        }
      }
}

Here the authentication is actually handling by other application, Once the user login it will send a request parameter (PARAMETER_VALUES) with some information.

We are using JSF 2.1.9 & Tomcat 6.0.35. i am getting an error at this line from Filter FacesContext context = FacesUtil.getFacesContext(req, res);

Error stack trace:

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)

When i see the source code of Tomcat 6.0.35 at the line stated in error, if (!getMethod().equalsIgnoreCase("POST")) return; cannot find much information here.

도움이 되었습니까?

해결책

You cannot access the FacesContext in a filter because the FacesContext is initialized by the FacesServlet, and your filter is processed before the request arrives to the servlet.

If it works sometimes, it is probably because of a side effect (JSF creates one FacesContext for every request, every request is bound to a Thread and Threads are reused by the servlet container).

I'm also wondering why are you trying to reinvent the wheel by implementing you own security filters. There is already existing solution which are available (like Spring Security or standard JEE security) and well tested.

See this question for more information from BalusC:

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top