How can I switch security model in runtime so that
Authentication
, andAuthentication
I think I resolved (2) but cannot quite figure out (1).
Spring Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").authenticated().and()
.addFilterBefore(switchingFilter);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(switchingAuthenticationProvider);
}
@Bean
public SwitchingAuthenticationProvider switchingAuthenticationProvider() {
return new SwitchingAuthenticationProvider();
}
@Bean
public SwitchingFilter switchingFilter() {
return new SwitchingFilter();
}
}
The SwitchingAuthenticationProvider
is straight forward: simply delegate to some other AuthenticationProvder
(i.e., LDAP/OAUTH2 or otherwise)
(inspired by Switching authentication approaches at runtime with Spring Security).
public class SwitchingAuthenticationProvider implements AuthenticationProvider {
private AuthenticationProvider[] authProviders = // ...
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return authProvider[i].authenticate(authentication);
}
}
But what creates the Authentication
? As I understand it one option is to let the GenericFilterBean
create the Authentication
as illustrated below.
public class SwitchingFilter extends GenericFilterBean {
private AuthProviderService authProviders = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Authentication authentication = authProviders.getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
}
}
... where an AuthProviderService
would delegate to something that creates an authentication
. But how can I plug it with e.g., the equivalent of HttpSecurity#httpBasic()
or HttpSecurity#openIdLogin()
?
Bonus question: What's the difference between HttpSecurity#authenticationProvider(..)
and AuthenticationManagerBuilder.authenticationProvider(..)
?
It appears the Filter
is responsible to create the Authentication
(not sure if anything else is too).
The AnonymousAuthenticationFilter
as an example
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(
createAuthentication((HttpServletRequest) req));
}
Similar I think the SwitchingFilter
should be similar to SwitchingAuthenticationProvider
public class SwitchingFilter extends GenericFilterBean {
private Filter[] filters = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
filters[i].doFilter(request, response, chain);
// do filterChain.doFilter(request, response); ??
}
}
.. for some mechanism of selecting a suitable index i
.