JSF form-login-page redirect hits before my filter

2019-02-20 14:27发布

问题:

I'm trying to implement a remember-me function in my java ee 6 application, but I have issues combining it with the build-in security feature. I have the following configuration in my web.xml:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>my-realm</realm-name>
    <form-login-config>
        <form-login-page>/login.jsf</form-login-page>
        <form-error-page>/login.jsf</form-error-page>
    </form-login-config>
</login-config>

What I'm trying to create is a filter that automatically logs a person in of their session is expired, if they have a cookie containing some data. This works, but when the filter is called, the redirect to login.jsf has already come into effect, before I have a change to do anything about it. I assumed that filters are called before java ee's own security system since they actually are called on secured pages, but this seems to not be the case. Is there some way to let the user come to the same page that they requested instead of being redirected to login.jsf?

Filter:

@WebFilter(
    filterName="authFilter",
    servletNames={
        "Faces Servlet"
    }
)
public class AuthFilter implements Filter {

    public AuthFilter() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        User user = (User)req.getSession().getAttribute("user");
        if(user == null){
            String uuid = CookieUtil.getCookieValue(req, "rememberme");
            if(uuid != null){
                UserBean userBean = EJBUtil.lookup(UserBean.class);
                RememberMe rememberme = userBean.findRememberMe(uuid);
                if(rememberme != null){
                    user = rememberme.getUser();
                    try{
                        req.login(user.getEmail(), user.getPasswordDigest());
                        req.getSession().setAttribute("user", user);
                        CookieUtil.addCookie(res, "rememberme", uuid, CookieUtil.AGE_ONE_YEAR);
                    }catch(ServletException e){}
                }
                else{
                    CookieUtil.removeCookie(res, "rememberme");
                }
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

回答1:

Container managed authentication is indeed invoked before all filters. This is a security restriction.

You've basically 3 options:

  • Use programmatic filtering and login instead so that you have more finer grained control.
  • Do the job in preRenderView event method of the bean associated with login.jsf instead.
  • Grab a framework which supports "Remember me" facility on top of container managed security transparently, such as Apache Shiro or Spring Security.