Фильтр сервлетов (автологин) имеет приоритет над декларативными проверками безопасности - PullRequest
3 голосов
/ 01 декабря 2011

Короткий вопрос .Как можно выполнить фильтры сервлетов до выполнения декларативной проверки безопасности?

Длинный вопрос .Для моего веб-приложения я пытаюсь управлять всеми своими требованиями безопасности, используя декларативную безопасность сервера: я установил ограничение безопасности на <url-pattern>/secure/*</url-pattern> с <auth-method>FORM</auth-method> и <form-login-page>/sign-in.xhtml</form-login-page>.

, чтобы обеспечить (основанная на cookie) функция «запомнить меня», я установил фильтр сервлетов, который перехватывает каждый запрос, проверяет, не вошел ли пользователь в систему, проверяет, может ли он войти в систему автоматически (через cookie), в конечном итоге входит в систему, используя сервлет на основеlogin.

<filter-mapping>
    <filter-name>CustomLoginFilter</filter-name>
    <url-pattern>*.xhtml</url-pattern>
</filter-mapping>

Теперь, если пользователь открывает свой браузер и подключается к mysite.com, все просто работает.Но если пользователь открывает свой браузер и делает прямой запрос к чему-то вроде mysite.com/secure/secret.xhtml, я наблюдаю следующее поведение:

  1. GET /secure/secret.xhtml
  2. бэк-компонентовсоздаются экземпляры log-in.xhtml (FacesContext доступен)
  3. вызывается CustomLoginFilter.doFilter (), (FacesContext равен NULL)

Это, очевидно, препятствует всему процессу.Я не могу найти способ дать преимущество моему CustomLoginFilter над сервером «декларативный фильтр безопасности» (или что-то еще);изменение порядка объявлений в web.xml тоже не помогает ... есть идеи?Спасибо!

1 Ответ

3 голосов
/ 01 декабря 2011

Как выполнить фильтры сервлетов до выполнения декларативной проверки безопасности?

Это невозможно из-за спецификаций и ограничений безопасности.

Ваша лучшая ставка - перехватить событие preRenderView на странице входа и использовать программный вход в систему с помощью нового сервлета 3.0 HttpServletRequest#login().

Е.Г.

<f:event type="preRenderView" listener="#{authenticator.checkAutoLogin}" />

с чем-то вроде

public void checkAutoLogin() throws IOException {
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    Cookie autoLogin = externalContext.getRequestCookieMap().get("autoLoginCookieName");

    if (autoLogin != null) {
        User user = decryptCookieValueAndExtractUser(autoLogin.getValue()); // Yes, it must be encrypted! Otherwise a too easy hack.

        if (user != null) {
            HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();

            try {
                request.login(user.getName(), user.getPassword());
                String originalRequestURI = externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
                externalContext.redirect(originalRequestURI != null ? originalRequestURI : "someDefaultIndex.xhtml");
            } catch (ServletException e) {
                // Login failed. It's up to you how to handle it.
            }
        }
    }
}
...