spring-security 用于不同API端点的Spring多个身份验证方法

xqkwcwgp  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(163)

我想检查不同端点的不同身份验证方法。我想使用的方法是x509和jwt。我需要对特定端点使用x509,而对所有其他请求使用JWT。
以下是我的Web安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                .antMatchers("/api/transaction/testf").authenticated().and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(new X509UserDetailsService())
                ;
        }
    }

    @Configuration
    @Order(2)
    public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                .antMatchers("/oauth/token", "/api/dealer/login").permitAll()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                ;
        }

    }
}

此配置只检查 /api/transaction/testf 端点是否有x509证书,并允许所有其他端点响应。我需要其他端点返回503,而不使用jwt令牌。

2ledvvac

2ledvvac1#

您有两个筛选器链。它们都没有正确配置http.antMatcher的入口点模式。这意味着它们被配置为使用/**作为它们的入口点模式。
比如说

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().fullyAuthenticated()

就像是说:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/**")
            .authorizeRequests()
                .anyRequest().fullyAuthenticated()

我们要说的是

  1. http-安全筛选器链
  2. http.antMatcher-安全筛选器链的入口点
  3. http.authorizeRequests-我的端点访问限制的开始
  4. http.authorizeRequests.antMatchers-具有特定访问权限的URL列表
    所以你需要做的就是改变你的@Order(1)过滤器链来缩小模式的范围。http.antMatcher("/api/transaction/**")
    现在,您的配置如下所示
@Configuration
    @Order(1)
    public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/transaction/**") //customized entry point
                .authorizeRequests()
                .antMatchers("/api/transaction/testf").authenticated().and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(new X509UserDetailsService())
                ;
        }
    }

    @Configuration
    @Order(2)
    public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/**") //this is default
                .authorizeRequests()
                .antMatchers("/oauth/token", "/api/dealer/login").permitAll()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                ;
        }

使用您现有的配置,名为ApiWebSecurityConfig的过滤器链将捕获所有调用。另一个过滤器链ApiTokenSecurityConfig从未使用过。

pkln4tw6

pkln4tw62#

由于WebSecurityConfigurerAdapter@Deprecated,因此最好使用多个SecurityFilterChain(请参阅更新的多个HttpSecurity):

@Bean
    @Order(1)                                                        
    public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
        http
            .antMatcher("/api/**")                                   
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().hasRole("ADMIN")
            )
            .httpBasic(withDefaults());
        return http.build();
    }

    @Bean                                                            
    public SecurityFilterChain formLoginFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .formLogin(withDefaults());
        return http.build();
    }

相关问题