#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 через браузер пользователя) и, вероятно, приведет к снижению быстродействия приложения.