我想根据可配置属性来配置实际使用的 SecurityFilterChain Bean。
我们有一个相同的应用程序,它支持不同类型的安全性。
@Configuration
@EnableWebSecurity
class SecurityConfiguration {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()).csrf(AbstractHttpConfigurer::disable);
return httpSecurity.build();
}
@Bean
public SecurityFilterChain securityFilterChainX509(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)");
return httpSecurity.build();
}
@Bean
public SecurityFilterChain securityFilterChainJWT(HttpSecurity httpSecurity) throws Exception {
}
[...]
}
我在这里仅粘贴了一个示例,但请想象这个文件充满了具有多种身份验证类型的 SecurityFilterChain bean,让我们想象有 50 种。
用例是同一个应用程序的每个实例都有自己的安全配置。
例如,部署在美国的应用程序需要检查客户端证书,因此需要使用 securityFilterChainX509 bean,而部署在法国的相同应用程序需要检查用户名密码,而部署在日本的应用程序则需要另一种类型的身份验证,等等。
到目前为止,我们正在使用一种相当“奇怪”的方法,即基于配置文件的方法。
我的意思是:
@Bean
@Profile({"canada", "brazil"})
SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()).csrf(AbstractHttpConfigurer::disable);
return httpSecurity.build();
}
@Bean
@Profile({"usa", "egypt"})
public SecurityFilterChain securityFilterChainX509(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)");
return httpSecurity.build();
}
@Bean
@Profile({"germany"})
public SecurityFilterChain securityFilterChainJWT(HttpSecurity httpSecurity) throws Exception {
}
虽然这种方法有效,但也存在缺点,它要求我们:
- 维护许多 application-profile.properties,只是为了获取正确的 bean。
- 当我们需要改变时(今天,巴西使用不安全的,明天,它需要 JWT),我们也需要改变代码。
(如果可能的话,真的想避免使用个人资料)
问题:
有没有一种方法,没有配置文件,但具有可配置的属性,例如
@Value("${the.security.bean.to.use}")
private String configuredSecurityBeanToUse;
配置要使用的实际 SecurityFilterChain bean?
是的。您可以根据您定义的属性初始化 bean。您需要
@ConditionalOnProperty
在 bean 方法上添加注释。@ConditionalOnProperty
将检查属性值是否具有您定义的值,只有该 bean 才会被初始化。当未定义任何属性时,将使用matchIfMissing属性,然后它将匹配条件并初始化该 bean。因此,对于相同 bean 类型的初始化,必须使用一次。在application.properties文件中,您需要定义以下配置以使用证书安全。
@ConditionalOnProperty文档 示例,包含详细信息