带有Spring Boot的Spring Security:将基本身份验证与JWT令牌身份验证混合 [英] Spring Security with Spring Boot: Mix Basic Authentication with JWT token authentication
问题描述
我试图让Spring Security的基本身份验证与JWT令牌身份验证并存,但没有成功.我已经为我的Web控制台和JWT实现了基本身份验证,以保护许多API端点.这是我的配置:
I am trying to get Spring Security's basic authentication to work side by side with JWT token authentication with no success. I have implemented basic authentication for my web console and JWT to secure a number of API endpoints. Here's my config:
@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错误. 任何帮助将不胜感激.
I have noticed that the configuration I annotate with Order(1) is the one that is picked by Spring Security and the other is completely ignored. Like in the above config, I get 401 error if I try to access /console/login. Any help would be much appreciated.
推荐答案
之所以如此,是因为ApiWebSecurityConfigurationAdapter
和FormLoginWebSecurityConfig
都不使用antMatcher()
.这意味着即使以后使用antMatchers()
,这两个安全配置也将处理所有路径.因此,具有最低顺序(@Order(1)
)的配置将处理所有操作,而其他配置则不执行任何操作.
The reason why is because neither ApiWebSecurityConfigurationAdapter
nor FormLoginWebSecurityConfig
uses the antMatcher()
. This means that both security configurations will handle all paths, even though you're using antMatchers()
afterwards. Due to this, the configuration with the lowest order (@Order(1)
) will handle everything, while the other one will do nothing.
文档:
http.antMatcher
声明此HttpSecurity
仅适用于以/api/
The
http.antMatcher
states that thisHttpSecurity
will only be applicable to URLs that start with/api/
因此,要解决此问题,您必须将antMatcher
置于您的一种配置(或两种配置)中.例如,如果仅将表单登录名应用于/console/login
和/console/home
,则可以将配置更改为:
So, to fix this problem, you have to povide an antMatcher
to one of your configurations (or both). For example, if the form login should only be applied to /console/login
and /console/home
, you could change the configuration to:
@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();
}
有关此主题的另一本好书是这个问题:何时使用Spring Security`s antMatcher()?
Another good read about this topic is this question: When to use Spring Security`s antMatcher()?
请注意,您不应该像添加.csrf().disable()
那样两次使用http
构建器,就像我在上面的代码中所做的那样,将其添加到其他构建器中.
Please note that you shouldn't use the http
builder twice like you did to add the .csrf().disable()
, add it to the other builder like I did in the code above.
另外请注意,您可能必须更改订单.您应该以最详细的antMatcher()
(在这种情况下为FormLoginWebSecurityConfig
)对配置进行订购.
Also be aware that you'll likely have to change the order. You should put the order on the configuration with the most detailed antMatcher()
, in this case FormLoginWebSecurityConfig
.
这篇关于带有Spring Boot的Spring Security:将基本身份验证与JWT令牌身份验证混合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!