领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多在 Spring Security 5.7.0-M2 中,我们弃用了 WebSecurityConfigurerAdapter
,因为我们鼓励用户转向基于组件的安全配置。
为了协助向这种新的配置风格过渡,我们编制了一份常见用例和今后建议的替代方案列表。
在下面的示例中,我们遵循最佳实践,使用 Spring Security lambda DSL 和方法 HttpSecurity#authorizeHttpRequests
来定义我们的授权规则。如果您不熟悉 lambda DSL,可以在这篇博文中了解它。如果您想了解更多关于我们为什么选择使用 HttpSecurity#authorizeHttpRequests
的信息,可以查看参考文档。
在 Spring Security 5.4 中,我们引入了通过创建 SecurityFilterChain
bean 来配置 HttpSecurity
的能力。
下面是一个使用 WebSecurityConfigurerAdapter
的配置示例,它使用 HTTP Basic 保护所有端点
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
}
}
展望未来,推荐的做法是注册一个 SecurityFilterChain
bean
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
}
在 Spring Security 5.4 中,我们还引入了 WebSecurityCustomizer
。
WebSecurityCustomizer
是一个回调接口,可用于自定义 WebSecurity
。
下面是一个使用 WebSecurityConfigurerAdapter
的配置示例,它忽略与 /ignore1
或 /ignore2
匹配的请求
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/ignore1", "/ignore2");
}
}
展望未来,推荐的做法是注册一个 WebSecurityCustomizer
bean
@Configuration
public class SecurityConfiguration {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}
}
警告:如果您正在配置 WebSecurity
以忽略请求,请考虑使用 HttpSecurity#authorizeHttpRequests
通过 permitAll
代替。有关更多详细信息,请参阅 configure
的Javadoc。
在 Spring Security 5.7 中,我们引入了 EmbeddedLdapServerContextSourceFactoryBean
、LdapBindAuthenticationManagerFactory
和 LdapPasswordComparisonAuthenticationManagerFactory
,它们可用于创建嵌入式 LDAP 服务器和执行 LDAP 身份验证的 AuthenticationManager
。
下面是一个使用 WebSecurityConfigurerAdapter
的配置示例,它创建了一个嵌入式 LDAP 服务器和一个使用绑定身份验证执行 LDAP 身份验证的 AuthenticationManager
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDetailsContextMapper(new PersonContextMapper())
.userDnPatterns("uid={0},ou=people")
.contextSource()
.port(0);
}
}
展望未来,推荐的做法是使用新的 LDAP 类
@Configuration
public class SecurityConfiguration {
@Bean
public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
contextSourceFactoryBean.setPort(0);
return contextSourceFactoryBean;
}
@Bean
AuthenticationManager ldapAuthenticationManager(
BaseLdapPathContextSource contextSource) {
LdapBindAuthenticationManagerFactory factory =
new LdapBindAuthenticationManagerFactory(contextSource);
factory.setUserDnPatterns("uid={0},ou=people");
factory.setUserDetailsContextMapper(new PersonContextMapper());
return factory.createAuthenticationManager();
}
}
下面是一个使用 WebSecurityConfigurerAdapter
和嵌入式 DataSource
的配置示例,该 DataSource
使用默认模式初始化,并且只有一个用户
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
auth.jdbcAuthentication()
.withDefaultSchema()
.dataSource(dataSource())
.withUser(user);
}
}
推荐的做法是注册一个 JdbcUserDetailsManager
bean
@Configuration
public class SecurityConfiguration {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
.build();
}
@Bean
public UserDetailsManager users(DataSource dataSource) {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
users.createUser(user);
return users;
}
}
注意:在这些示例中,我们出于可读性使用 User.withDefaultPasswordEncoder()
方法。它不适用于生产环境,我们建议您在外部对密码进行哈希处理。一种方法是使用 Spring Boot CLI,如参考文档中所述。
下面是一个使用 WebSecurityConfigurerAdapter
的配置示例,它使用单个用户配置内存用户存储
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
auth.inMemoryAuthentication()
.withUser(user);
}
}
推荐的做法是注册一个 InMemoryUserDetailsManager
bean
@Configuration
public class SecurityConfiguration {
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
注意:在这些示例中,我们出于可读性使用 User.withDefaultPasswordEncoder()
方法。它不适用于生产环境,我们建议您在外部对密码进行哈希处理。一种方法是使用 Spring Boot CLI,如参考文档中所述。
要创建可用于整个应用程序的 AuthenticationManager
,您可以简单地将 AuthenticationManager
作为 @Bean
注册。
这种类型的配置如上所示,在LDAP 身份验证示例中。
在 Spring Security 5.6 中,我们引入了方法HttpSecurity#authenticationManager,该方法覆盖特定 SecurityFilterChain
的默认 AuthenticationManager
。下面是一个配置示例,它将自定义 AuthenticationManager
设置为默认值
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated()
)
.httpBasic(withDefaults())
.authenticationManager(new CustomAuthenticationManager());
return http.build();
}
}
可以在自定义 DSL中访问本地 AuthenticationManager
。这实际上是 Spring Security 在内部实现 HttpSecurity.authorizeRequests()
等方法的方式。
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
http.addFilter(new CustomFilter(authenticationManager));
}
public static MyCustomDsl customDsl() {
return new MyCustomDsl();
}
}
然后,在构建 SecurityFilterChain
时可以应用自定义 DSL
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
http.apply(customDsl());
return http.build();
}
我们很高兴与您分享这些更新,并期待着通过您的反馈进一步增强 Spring Security!如果您有兴趣贡献,可以在GitHub上找到我们。