如何使用spring security在运行时切换安全模型?

时间:2016-03-01 17:29:43

标签: java spring-mvc spring-security spring-ldap spring-oauth2

如何在运行时切换安全模型以便

  1. 现有的spring安全组件可以生成Authentication
  2. 现有的spring安全组件可以验证Authentication
  3. 我认为我解决了(2),但无法弄清楚(1)

    Spring Security配置

    @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();
        }
    }
    

    SwitchingAuthenticationProvider很简单:只需委托给其他AuthenticationProvder(即LDAP / OAUTH2或其他)

    (灵感来自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);
        }
    }
    

    但是什么创造了Authentication?据我了解,一个选项是让GenericFilterBean创建Authentication,如下图所示。

    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);
       }
    }
    

    ... AuthProviderService将委托给创建authentication的内容。但是我如何插入它,例如相当于HttpSecurity#httpBasic()HttpSecurity#openIdLogin()

    奖金问题:HttpSecurity#authenticationProvider(..)AuthenticationManagerBuilder.authenticationProvider(..)之间有什么区别?

1 个答案:

答案 0 :(得分:1)

Filter 似乎负责创建Authentication(不确定是否还有其他内容)。

AnonymousAuthenticationFilter为例

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {

    if (SecurityContextHolder.getContext().getAuthentication() == null) {
        SecurityContextHolder.getContext().setAuthentication(
                createAuthentication((HttpServletRequest) req));
}

类似我认为SwitchingFilter应与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); ??
   }
}

..用于选择合适索引i的某种机制。