【问题标题】:Spring Security with Spring Boot: Mix Basic Authentication with JWT token authentication [duplicate]带有 Spring Boot 的 Spring Security:将基本身份验证与 JWT 令牌身份验证混合使用 [重复]
【发布时间】:2018-06-21 14:42:56
【问题描述】:

我正在尝试让 Spring Security 的基本身份验证与 JWT 令牌身份验证并行工作,但没有成功。我已经为我的 Web 控制台和 JWT 实现了基本身份验证,以保护许多 API 端点。这是我的配置:

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MultiHttpSecurityConfig {

@Autowired
private UserDetailsService userDetailsService;    

@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder
            .userDetailsService(this.userDetailsService)
            .passwordEncoder(bCryptPasswordEncoder());
}

@Bean
public PasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

/**
 * 
 * API Security configuration
 *
 */
@Configuration
@Order(1) 
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter{

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity   
            .csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()                
            // don't create session
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests().antMatchers("/api/**","/refresh/**").authenticated()
            .antMatchers("/auth/**").permitAll().anyRequest().authenticated();               
        // Custom JWT based security filter
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        // disable page caching
        httpSecurity.headers().cacheControl();
    }
}

/**
 * 
 * Form login security configuration
 *
 */
@Configuration
public static class FormLoginWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ConsoleAuthenticationEntryPoint consoleAuthenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {          
        http.httpBasic().and().exceptionHandling().authenticationEntryPoint(
                consoleAuthenticationEntryPoint).and()
         .authorizeRequests().antMatchers("/console/**").authenticated()
         .antMatchers(HttpMethod.GET,
                    "/*.html",
                    "/favicon.ico",
                    "/**/*.html",
                    "/**/*.css",
                    "/**/*.js").permitAll()
         .anyRequest().authenticated()
         .and()
         .formLogin().defaultSuccessUrl("/console/home")
         .loginPage("/console/login")
         .permitAll()
         .and()
         .logout()
         .permitAll();
        http.csrf().disable();
    }
}

}

我注意到我用 Order(1) 注释的配置是 Spring Security 选择的配置,而另一个则被完全忽略。就像上面的配置一样,如果我尝试访问 /console/login,我会收到 401 错误。 任何帮助将不胜感激。

【问题讨论】:

    标签: java spring-boot spring-security jwt


    【解决方案1】:

    原因是因为ApiWebSecurityConfigurationAdapterFormLoginWebSecurityConfig 都没有使用antMatcher()。这意味着两种安全配置都将处理所有路径,即使您之后使用antMatchers()。因此,最低阶的配置 (@Order(1)) 将处理所有事情,而另一个则什么也不做。

    docs中也提到了这一点:

    http.antMatcher 声明此HttpSecurity 仅适用于以/api/ 开头的网址

    因此,要解决此问题,您必须为您的一个配置(或两者)提供antMatcher。例如,如果表单登录只应用于/console/login/console/home,您可以将配置更改为:

    @Override
    protected void configure(HttpSecurity http) throws Exception {          
        http
            .antMatcher("/console/**") // Add this
            .httpBasic().and()
            .exceptionHandling().authenticationEntryPoint(consoleAuthenticationEntryPoint).and()
            .authorizeRequests().antMatchers("/console/**").authenticated()
            .antMatchers(HttpMethod.GET,
                    "/*.html",
                    "/favicon.ico",
                    "/**/*.html",
                    "/**/*.css",
                    "/**/*.js").permitAll()
            .anyRequest().authenticated().and()
            .formLogin().defaultSuccessUrl("/console/home")
            .loginPage("/console/login").permitAll().and()
            .logout().permitAll().and() // Make sure to use .and() to add the .csrf()
            .csrf().disable();
    }
    

    关于这个主题的另一个好读物是这个问题:When to use Spring Security`s antMatcher()?

    请注意,您不应像添加 .csrf().disable() 那样两次使用 http 构建器,而是像我在上面的代码中那样将其添加到另一个构建器。

    另外请注意,您可能需要更改订单。您应该在配置最详细的antMatcher() 上下订单,在这种情况下为FormLoginWebSecurityConfig

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 2017-07-10
      • 2022-08-16
      • 1970-01-01
      • 2018-02-27
      • 1970-01-01
      • 2020-02-04
      • 2015-07-22
      • 2017-11-02
      相关资源
      最近更新 更多