Пользовательский клапан аутентификации SAML в Spring Boot Embedded Tomcat - не применять к конечным точкам привода
Старый общий метод Tomcat
У меня есть собственный аутентификационный клапан SAML 2.0, который я сейчас использую на некоторых автономных веб-серверах Tomcat для реализации единого входа.
Чтобы реализовать это, мы добавляем клапан в файл context.xml сервера tomcat, например, (некоторые примеры значений используются вместо реальных значений):
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Valve className="example.CustomIdpValve"
idp="default" issuerName="SAMLIssuer"
idpUrl="https://example.idp.com/sso/"
certificatePath="${catalina.base}/conf/idp.cer"
/>
</Context>
Затем мы будем контролировать, какие конечные точки должны быть защищены на основе web.xml.
Новый Spring Boot встроенный метод Tomcat
Теперь мы используем этот клапан в автономных приложениях с пружинной загрузкой, работающих через встроенный tomcat с пружинной загрузкой. Мы добавляем один и тот же пользовательский аутентификационный клапан в эти приложения через конфигурацию Java:
@Bean
public ConfigurableServletWebServerFactory embeddedServletContainerCustomizer() {
final CustomIdpValve customIdpValve = new CustomIdpValve();
final Valve singleSignOnValve = new SingleSignOn();
final TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addContextValves(customIdpValve);
factory.addContextValves(singleSignOnValve);
return factory;
}
Затем мы требуем, чтобы определенные роли были включены в UserPrincipal для доступа к приложению. Это снова настраивается через настройку Java (роли извлекаются из application.properties):
@Component
public class WebAppInitializer implements ServletContextInitializer {
private final String[] roles;
public WebAppInitializer(@Value("${tomcat.embedded.roles}") final String[] roles) {
this.roles = roles;
}
public void onStartup(final ServletContext container) {
final ServletRegistration.Dynamic servlet = (ServletRegistration.Dynamic) container.getServletRegistration("default");
servlet.setServletSecurity(new ServletSecurityElement(new HttpConstraintElement(ServletSecurity.TransportGuarantee.NONE, roles)));
servlet.setServletSecurity(new ServletSecurityElement(new HttpConstraintElement(ServletSecurity.TransportGuarantee.CONFIDENTIAL, roles)));
}
}
Эта проблема
Это работает нормально - новые приложения весенней загрузки перенаправляют любой входящий запрос в IdP для аутентификации, которая затем отправляет ответ SAML обратно на первоначально запрошенный URL, и страница загружается, как и ожидалось.
Проблема в том, что мы включили конечные точки исполнительного механизма пружинной загрузки, которые должны обойти эту аутентификацию. В частности, нам нужна конечная точка проверки работоспособности /actuator/health
быть незащищенным, чтобы его можно было использовать в качестве зонда готовности для кубернетов.
Я не могу определить способ применения этого ServletSecurity
на основе пути для каждого запроса, поэтому мы не требуем никакой аутентификации для каких-либо запросов к /actuator/*
дорожка.
Возможно ли что-то подобное?
1 ответ
Нашел очень простое решение.
Если вы измените management.server.port
Если порт, отличный от используемого основного контекста приложения, Spring Boot автоматически создаст дочерний контекст приложения для конечных точек привода.
Таким образом, ServletSecurity
добавленное мной применяется только к родительскому контексту приложения по умолчанию, а конечные точки привода, работающие на другом порту, не требуют аутентификации.