我试图让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)注释的配置是SpringSecurity选择的配置,而另一个则被完全忽略。像上面的配置一样,如果尝试访问/ console / login,则会出现401错误。任何帮助将非常感激。
原因是因为既不使用ApiWebSecurityConfigurationAdapter也不FormLoginWebSecurityConfig使用antMatcher()。这意味着,即使您antMatchers()以后使用,这两个安全配置也将处理所有路径。因此,具有最低顺序(@Order(1))的配置将处理所有操作,而另一配置则不执行任何操作。
ApiWebSecurityConfigurationAdapter
FormLoginWebSecurityConfig
antMatcher()
antMatchers()
@Order(1)
在文档中也提到了这一点:
在http.antMatcher美国,这HttpSecurity将只适用于与开头的网址/api/
http.antMatcher
HttpSecurity
/api/
因此,要解决此问题,您必须将an放置antMatcher到您的一个配置(或两个配置)中。例如,如果表单登录名应仅应用于/console/login和/console/home,则可以将配置更改为:
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(); }
请注意,您不应http像添加那样两次使用构建.csrf().disable()器,就像我在上面的代码中一样,将其添加到其他构建器中。
http
.csrf().disable()
另请注意,您可能必须更改顺序。antMatcher()在这种情况下,您应该以最详细的顺序订购配置FormLoginWebSecurityConfig。