Предварительная проверка подлинности Spring SAML на IDP

#java #spring #spring-security #saml #spring-saml

#java #весна #spring-безопасность #saml #spring-saml

Вопрос:

Я пишу несколько веб-приложений, основанных как на Spring security, так и на расширении spring security saml (RC2).

У меня есть единый вход для работы с несколькими поставщиками услуг и поставщиком удостоверений базовым способом (на основе примера, определенного в документах spring saml).

Когда пользователь обращается к защищенному ресурсу на SP, он перенаправляется на защищенный ресурс на IDP. Таким образом, поскольку пользователь еще не вошел в систему, он перенаправляется на страницу входа в систему (стандартный материал Spring security). После входа в систему воспроизводится исходный запрос, выполняется запрос / ответ AuthnRequest, и пользователь перенаправляется на исходный защищенный ресурс.

Теперь у меня есть требование, гарантирующее, что все поставщики услуг должны запрашивать поставщика удостоверений, входит ли пользователь в систему перед каждым запросом (вместо того, чтобы делать это локально в SP).

Насколько я понимаю, локальный (SP) и удаленный (IDP) контекст безопасности сохраняется и запрашивается во время каждого запроса, и если нет допустимого контекста, пользователь затем перенаправляется поставщику удостоверений для прохождения процесса аутентификации.

Итак, мой вопрос в том, есть ли способ настроить безопасность saml / spring на стороне SP, чтобы всегда «ping» или попросить IDP проверить, зарегистрирован ли текущий пользователь, или это ненужные / неподдерживаемые вещи.

заранее спасибо

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

1. разве это не ненужный переход туда и обратно? Я имею в виду, что у меня есть конфигурация, в которой у меня много войн, и у меня есть одна война SP. Таким образом, я могу настроить все URL-адреса, которые должны быть безопасными. и все мои войны перенаправляются на мой SP, который отправится в IDP, только если аутентификация недоступна. Это подход, которому нужно следовать, отправляя запрос в IDP по каждому запросу, не рекомендуется. 🙂

Ответ №1:

Вы правы, Spring SAML запрашивает локальный контекст безопасности во время каждого запроса и перенаправляет пользователя в IDP, как только он становится недействительным.

Типичным механизмом, который определяет, когда контекст становится недействительным, является использование атрибута SAML SessionNotOnOrAfter . Атрибут включен в утверждение AuthenticationStatement, отправленное обратно из IDP. Spring SAML автоматически повторно аутентифицирует пользователя, как только время превысит значение, указанное в SessionNotOnOrAfter .

В случае, если вы хотите повторно проходить аутентификацию при каждом запросе, вы можете, например, добавить новый пользовательский фильтр, подобный этому:

 package fi.test;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class ReAuthenticateFilter extends GenericFilterBean {

    private static final String FILTER_APPLIED = "__spring_security_filterReAuthenticate_filterApplied";

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        invoke(fi);
    }

    protected void invoke(FilterInvocation fi) throws IOException, ServletException {

        if ((fi.getRequest() != null) amp;amp; (fi.getRequest().getAttribute(FILTER_APPLIED) != null)) {
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } else {
            if (fi.getRequest() != null) {
                fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
            }
        }

       Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        try {
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            if (authentication != null) {
                authentication.setAuthenticated(false);
            }
        }

    }

}
  

Затем вы должны включить фильтр в свою конфигурацию Spring:

 <security:http entry-point-ref="samlEntryPoint">
    <security:custom-filter after="SECURITY_CONTEXT_FILTER" ref="reAuthenticateFilter"/>
    ...
</security:http>

<bean id="reAuthenticateFilter" class="fi.test.ReAuthenticateFilter"/>
  

Повторная аутентификация при каждом запросе является довольно дорогостоящей операцией (обратный переход к IDP через браузер пользователя) и, вероятно, приведет к снижению быстродействия приложения.