Spring Security升级到5.7.1版本
1、背景
因为CVE-2022-22978安全问题
CVE-2022-22978 | In Spring Security versions 5.5.6 and 5.5.7 and older unsupported versions, RegexRequestMatcher can easily be misconfigured to be bypassed on some servlet containers. Applications using RegexRequestMatcher with . in the regular expression are possibly vulnerable to an authorization bypass. |
---|---|
项目中可能会有人用到RegexRequestMatcher
,考虑升级Spring Security版本到5.7.1。
2、POM文件
如果项目工程是带Spring父工程的情况下,可以直接重新指定版本号。如果不是,则按常规套路,动手排除老版本,新增新版本。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<properties>
...
<spring-security.version>5.7.1</spring-security.version>
</properties>
3、配置代码修改
在Spring Security的5.7.x版本下,WebSecurityConfigurerAdapter
类已经被废弃,后续版本将被移除,所以更新POM后WebSecurityConfigurerAdapter
有弃用告警(已被标记@Deprecated),但依旧可以使用。
3.1 HttpSecurity
改造前,类似如下的伪代码:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
...
.antMatcher("/**")
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
);
}
}
改造后,直接使用配置Bean的方式生成SecurityFilterChain
,如果有多条认证链,可以配置多个SecurityFilterChain
。
参考伪代码:
@Order(100)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
...
httpSecurity
...
...
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 自定义匿名访问所有url放行 : 允许匿名和带权限以及登录用户访问
.antMatchers(anonymousUrls.toArray(new String[0])).permitAll()
// 所有请求都需要认证
.anyRequest().authenticated();
//跨域
httpSecurity.addFilterBefore(corsFilter,UsernamePasswordAuthenticationFilter.class);
//用于携带token的认证
httpSecurity.addFilterBefore(jwtTokenFilter,UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
3.2 WebSecurity
如需WebSecurity.ignoring()
忽略某些URL请求,
改造前伪代码参考:
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
...
web.ignoring().antMatchers("/ignore1", "/ignore2");
}
}
改造后伪代码参考:
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// 不推荐使用,此类方式会直接跳过认证和授权。
return web -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}
4、Spring Security缺省配置
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnDefaultWebSecurity
@AutoConfigureBefore(SecurityAutoConfiguration.class)
@AutoConfigureAfter({ HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class, OAuth2ClientAutoConfiguration.class,
OAuth2ResourceServerAutoConfiguration.class, Saml2RelyingPartyAutoConfiguration.class })
public class ManagementWebSecurityAutoConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) -> {
requests.requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll();
requests.anyRequest().authenticated();
});
if (ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)) {
http.cors();
}
http.formLogin(Customizer.withDefaults());
http.httpBasic(Customizer.withDefaults());
return http.build();
}
}
在@ConditionalOnDefaultWebSecurity
注解中决定是否创建缺省的SecurityFilterChain
。
在WebSecurityConfiguration
配置类中,注入List<SecurityFilterChain>
时,没有找到@Order的排序的源码。版本(5.7.1)
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
this.securityFilterChains = securityFilterChains;
}