Перенаправление формы JSF-страницы входа в систему попадает перед моим фильтром

#security #java-ee-6 #servlet-filters

#Безопасность #java-ee-6 #сервлет-фильтры

Вопрос:

Я пытаюсь реализовать функцию запоминания меня в своем приложении Java ee 6, но у меня возникают проблемы с объединением ее со встроенной функцией безопасности. У меня есть следующая конфигурация в моем 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>
  

То, что я пытаюсь создать, — это фильтр, который автоматически регистрирует пользователя в том, что срок его сеанса истек, если у него есть файл cookie, содержащий некоторые данные. Это работает, но при вызове фильтра перенаправление на login.jsf уже вступило в силу, прежде чем я что-либо изменю, чтобы что-либо с этим сделать. Я предположил, что фильтры вызываются перед собственной системой безопасности java ee, поскольку они фактически вызываются на защищенных страницах, но, похоже, это не так. Есть ли какой-нибудь способ позволить пользователю перейти на ту же страницу, которую они запросили, вместо перенаправления на login.jsf?

Фильтр:

 @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:

Аутентификация, управляемая контейнером, действительно вызывается перед всеми фильтрами. Это ограничение безопасности.

В основном у вас есть 3 варианта:

  • Вместо этого используйте программную фильтрацию и войдите в систему, чтобы у вас был более точный контроль.
  • Вместо этого выполните задание в preRenderView методе событий компонента, связанного с login.jsf .
  • Возьмите фреймворк, который поддерживает функцию «Запомнить меня» поверх прозрачно управляемой безопасности контейнера, такой как Apache Shiro или Spring Security.

Комментарии:

1. 1. Похоже, что этот подход займет много времени, при этом безопасность ухудшится, и придется заново изобретать систему сопоставления URL-адресов и т.д. Просто для решения очень маленькой проблемы. 2. Как это поможет? Пользователь все равно будет перенаправлен на login.jsf, и я бы понятия не имел, откуда он взялся. 3. Я проверил Spring Security, но, похоже, у него был полностью свой собственный механизм безопасности, что означало бы необходимость в основном переделать весь мой код безопасности / конфигурацию. Даже если бы он поддерживал request.login(), мне не нужно было бы дублировать большинство моих настроек ограничений?

2. Shiro действительно выглядит интересно, если его можно легко реализовать

3. 1. Верно, вы в основном изобретаете некоторые шипы колеса. 2. Исходный URI должен быть доступен в качестве одного из атрибутов запроса (извините, не знаю ключ сверху, посмотрите на карту атрибутов запроса). 3. Я никогда не использовал Spring Security, но понимаю, что его можно использовать в сочетании с CMS (из документов SS: Хотя мы рекомендуем людям использовать Spring Security для аутентификации и не интегрировать с существующей аутентификацией, управляемой контейнером, она, тем не менее, поддерживается — как и интеграция с вашей собственной системой аутентификации. ).

4. около 2: HttpServletRequest.getRequestURI указывает на мою страницу входа в систему, а HttpServletRequest.getParameterMap пуст, поэтому я действительно не думаю, что исходный URL доступен.

5. Атрибуты запроса, а не параметры запроса. ExternalContext#getRequestMap() должен предоставить сопоставление их всех.