領先一步
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
。請參閱 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();
}
}
區域 AuthenticationManager
可以在自訂 DSL 中存取。實際上,這就是 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 上找到我們。