Могу ли я подключить несколько экземпляров AuthenticationEntryPoint
в Spring Security 3.2.4?
Я пытаюсь создать следующий сценарий:
AuthenticationEntryPoint
- LoginUrlAuthenticationEntryPoint
CLIENT-CERT
Когда пользователь пытается получить доступ к защищенному URL-адресу:
CLIENT-CERT
аутентификация завершается с ошибкой, если только они не предоставили действительный сертификат, соответствующий пользователю в UserService
. Стандартная x509
подлинности Spring x509
.CLIENT-CERT
, они FORM
на страницу проверки подлинности на основе FORM
. Я работаю на Tomcat 7.0.54 с clientAuth="want"
. Это отлично работает в "простой" настройке Spring Security, то есть с одним WebSecurityConfigurerAdapter
установленным в x509()
и другим набором для formLogin()
в соответствии с этим примером
Итак, я хочу, чтобы поток процессов выглядел следующим образом:
У меня был некоторый успех при динамическом изменении используемого метода проверки подлинности с помощью DelegatingAuthenticationEntryPoint
но:
AntPathRequestMatcher
для сопоставления, скажем, /form/**
для LoginUrlAuthenticationEntryPoint
сервлет аутентификации (/j_spring_security_check
) дает ошибку HTTP404
.AntPathRequestMatcher
для отображения, скажем, /cert/**
на Http403ForbiddenEntryPoint
данные пользователя не извлекаются из представленного клиентского сертификата, поэтому это дает ошибку HTTP403
.Я также не вижу, как заставить пользователя дважды пройти проверку подлинности.
Я использую java-config, а не XML.
Мой код:
У меня есть DelegatingAuthenticationEntryPoint
:
@Bean
public AuthenticationEntryPoint delegatingEntryPoint() {
final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = Maps.newLinkedHashMap();
map.put(new AntPathRequestMatcher("/basic/**"), new BasicAuthenticationEntryPoint());
map.put(new AntPathRequestMatcher("/cert/**"), new Http403ForbiddenEntryPoint());
final DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(map);
entryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"));
return entryPoint;
}
И моя configure
@Override
protected void configure(final HttpSecurity http) throws Exception {
defaultConfig(http)
.headers()
.contentTypeOptions()
.xssProtection()
.cacheControl()
.httpStrictTransportSecurity()
.addHeaderWriter(new XFrameOptionsHeaderWriter(SAMEORIGIN))
.and()
.authorizeRequests()
.accessDecisionManager(decisionManager())
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(delegatingEntryPoint())
.and()
.sessionManagement()
.maximumSessions(1)
.sessionRegistry(sessionRegistry())
.maxSessionsPreventsLogin(true);
}
Где decisionManager()
возвращает экземпляр UnanimousBased
. sessionRegistry()
возвращает экземпляр SessionRegistryImpl
. Оба метода - @Bean
.
Я добавляю пользовательский UserDetailsService
используя:
@Autowired
public void configureAuthManager(
final AuthenticationManagerBuilder authBuilder,
final InMemoryUserDetailsService authService) throws Exception {
authBuilder.userDetailsService(authService);
}
И у меня есть собственный FilterInvocationSecurityMetadataSource
сопоставленный с использованием BeanPostProcessor
как в этом примере.
Цепочка нескольких точек входа не будет работать.
Ваш лучший вариант здесь может состоять в том, чтобы просто настроить процесс регистрации форм, чтобы проверить наличие сертификата (до аутентификации пользователя). Это, вероятно, упростит конфигурацию в целом. Это было бы точно так же, как обычная форма входа в систему.
Работа, проделанная фильтром X509, весьма минимальна. Например, вы можете переопределить метод attemptAuthentication
, вызвать super.attemptAuthentication()
а затем проверить, соответствует ли информация о сертификате полученной информации о проверке подлинности пользователя.