简体   繁体   中英

How to switch security model in runtime with spring security?

How can I switch security model in runtime so that

  1. an existing spring security component can produce an Authentication , and
  2. an existing spring security component can validate the Authentication

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 (ie, 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 eg, 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 .

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM