Can I chain multiple instances of AuthenticationEntryPoint
in Spring Security 3.2.4?
I attempting to create the following scenario:
AuthenticationEntryPoint
used is LoginUrlAuthenticationEntryPoint
CLIENT-CERT
When a user attempts to access the secure URL:
CLIENT-CERT
then authentication fails unless they have provided a valid certificate the corresponds to a user in the UserService
. Standard Spring Security x509
authentication. CLIENT-CERT
, they are directed to a FORM
based authentication page. I am running on Tomcat 7.0.54 with clientAuth="want"
. This works perfectly in a "simple" Spring Security set up - ie with one WebSecurityConfigurerAdapter
set to x509()
and another set to formLogin()
as per this example
So, I want a process flow something like the following:
I have had some success with dynamically changing the used authentication method by using a DelegatingAuthenticationEntryPoint
but:
AntPathRequestMatcher
to map, say, /form/**
to a LoginUrlAuthenticationEntryPoint
the authentication servlet ( /j_spring_security_check
) gives a HTTP404
error. AntPathRequestMatcher
to map, say, /cert/**
to a Http403ForbiddenEntryPoint
the user's details are not extracted from the presented client certificate so this gives a HTTP403
error. I also cannot see how to force a user to authenticate twice .
I am using the java-config and not XML.
My code:
I have a 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;
}
And my 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);
}
Where decisionManager()
returns a UnanimousBased
instance. sessionRegistry()
returns a SessionRegistryImpl
instance. Both methods are @Bean
.
I add a custom UserDetailsService
using:
@Autowired
public void configureAuthManager(
final AuthenticationManagerBuilder authBuilder,
final InMemoryUserDetailsService authService) throws Exception {
authBuilder.userDetailsService(authService);
}
And I have a custom FilterInvocationSecurityMetadataSource
mapped using a BeanPostProcessor
as in this example .
Chaining multiple entry points won't really work.
Your best option here might be to just customize the form-login process to check for the certificate if it's needed (before authenticating the user). That would probably simplify the configuration overall. It would really just be the same as a normal form-login setup.
The work done by the X509 filter is quite minimal . So for example, you could override the attemptAuthentication
method, call super.attemptAuthentication()
and then check that the certificate information matches the returned user authentication information.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.