此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.1spring-doc.cn

配置迁移

以下步骤与有关如何配置 、 和 .HttpSecurityWebSecurityAuthenticationManagerspring-doc.cn

添加注释@Configuration

在 6.0 中,已从 、 、 和 中删除。@Configuration@EnableWebSecurity@EnableMethodSecurity@EnableGlobalMethodSecurity@EnableGlobalAuthenticationspring-doc.cn

为此,无论您在何处使用这些注释之一,都可能需要添加 . 例如,从以下位置更改:@Configuration@EnableMethodSecurityspring-doc.cn

@EnableMethodSecurity
public class MyConfiguration {
	// ...
}
@EnableMethodSecurity
open class MyConfiguration {
	// ...
}
@Configuration
@EnableMethodSecurity
public class MyConfiguration {
	// ...
}
@Configuration
@EnableMethodSecurity
open class MyConfiguration {
	// ...
}

使用新方法requestMatchers

在 Spring Security 5.8 中,antMatchersmvcMatchersregexMatchers 方法已被弃用,取而代之的是新的 requestMatchers 方法spring-doc.cn

新方法被添加到 authorizeHttpRequests、 、 CSRF 配置和任何其他具有专用方法的地方。 已弃用的方法在 Spring Security 6 中删除。requestMatchersauthorizeRequestsWebSecurityCustomizerRequestMatcherspring-doc.cn

这些新方法具有更安全的默认值,因为它们为您的应用程序选择最合适的实现。 总之,如果您的应用程序在 Classpath 中有 Spring MVC,则新方法会选择实现,如果 Spring MVC 不存在,则回退到实现(使行为与 Kotlin 等效方法保持一致)。RequestMatcherMvcRequestMatcherAntPathRequestMatcherspring-doc.cn

要开始使用新方法,您可以将已弃用的方法替换为新方法。例如,以下应用程序配置:spring-doc.cn

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

可以更改为:spring-doc.cn

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/user/**").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

如果您在 Classpath 中有 Spring MVC 并且正在使用这些方法,则可以将其替换为新方法,Spring Security 将为您选择实现。 以下配置:mvcMatchersMvcRequestMatcherspring-doc.cn

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .mvcMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

等效于:spring-doc.cn

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

如果要自定义 的属性,则现在可以使用 创建共享相同 servlet 路径的实例:servletPathMvcRequestMatcherMvcRequestMatcher.BuilderMvcRequestMatcherspring-doc.cn

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .mvcMatchers("/admin").servletPath("/path").hasRole("ADMIN")
                .mvcMatchers("/user").servletPath("/path").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

上面的代码可以使用 和 方法重写:MvcRequestMatcher.BuilderrequestMatchersspring-doc.cn

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
        MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
                .requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

如果您对新方法有疑问,您可以随时切换回您正在使用的实现。 例如,如果您仍然想使用 and implementations,则可以使用接受实例的方法:requestMatchersRequestMatcherAntPathRequestMatcherRegexRequestMatcherrequestMatchersRequestMatcherspring-doc.cn

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers(antMatcher("/user/**")).hasRole("USER")
                .requestMatchers(antMatcher(HttpMethod.POST, "/user/**")).hasRole("ADMIN")
                .requestMatchers(regexMatcher(".*\\?x=y")).hasRole("SPECIAL") // matches /any/path?x=y
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

请注意,上面的示例使用了 AntPathRequestMatcherRegexRequestMatcher 中的静态工厂方法来提高可读性。spring-doc.cn

如果您正在使用该接口,则可以替换已弃用的方法:WebSecurityCustomizerantMatchersspring-doc.cn

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
	return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}

与他们的对应物:requestMatchersspring-doc.cn

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
	return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}

同样,如果你正在自定义 CSRF 配置以忽略某些路径,你可以用方法替换已弃用的方法:requestMatchersspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf((csrf) -> csrf
            .ignoringAntMatchers("/no-csrf")
        );
    return http.build();
}

可以更改为:spring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf((csrf) -> csrf
            .ignoringRequestMatchers("/no-csrf")
        );
    return http.build();
}

使用新方法securityMatchers

在 Spring Security 5.8 中,弃用了 和 methods from,取而代之的是新方法。antMatchersmvcMatchersrequestMatchersHttpSecuritysecurityMatchersspring-doc.cn

请注意,这些方法与已弃用以支持这些方法的方法不同。 但是,这些方法与方法相似,因为它们将为您的应用程序选择最合适的实现。 总之,如果您的应用程序在 Classpath 中有 Spring MVC,则新方法会选择实现,如果 Spring MVC 不存在,则回退到实现(使行为与 Kotlin 等效方法保持一致)。 添加方法的另一个原因是为了避免与 .authorizeHttpRequestsrequestMatcherssecurityMatchersrequestMatchersRequestMatcherMvcRequestMatcherAntPathRequestMatchersecurityMatchersrequestMatchersauthorizeHttpRequestsspring-doc.cn

以下配置:spring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .antMatcher("/api/**", "/app/**")
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

可以使用以下方法重写:securityMatchersspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/api/**", "/app/**")
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

如果您在配置中使用自定义:RequestMatcherHttpSecurityspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .requestMatcher(new MyCustomRequestMatcher())
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

public class MyCustomRequestMatcher implements RequestMatcher {
	// ...
}

您可以使用以下方法执行相同的操作:securityMatcherspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher(new MyCustomRequestMatcher())
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

public class MyCustomRequestMatcher implements RequestMatcher {
	// ...
}

如果要在配置中组合多个 implementations:RequestMatcherHttpSecurityspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .requestMatchers((matchers) -> matchers
            .antMatchers("/api/**", "/app/**")
            .mvcMatchers("/admin/**")
            .requestMatchers(new MyCustomRequestMatcher())
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

您可以使用 :securityMatchersspring-doc.cn

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatchers((matchers) -> matchers
            .requestMatchers("/api/**", "/app/**", "/admin/**")
            .requestMatchers(new MyCustomRequestMatcher())
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

如果您在选择实现的方法中遇到问题,您始终可以自己选择实现:securityMatchersRequestMatcherRequestMatcherspring-doc.cn

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatchers((matchers) -> matchers
            .requestMatchers(antMatcher("/api/**"), antMatcher("/app/**"))
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers(antMatcher("/api/admin/**")).hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

停止使用WebSecurityConfigurerAdapter

发布 BeanSecurityFilterChain

Spring Security 5.4 引入了发布 bean 的功能,而不是扩展。 在 6.0 中,已删除。 要为此更改做好准备,您可以替换如下结构:SecurityFilterChainWebSecurityConfigurerAdapterWebSecurityConfigurerAdapterspring-doc.cn

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    @Override
    override fun configure(val http: HttpSecurity) {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }

            httpBasic {}
        }
    }

}
@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

}
@Configuration
open class SecurityConfiguration {

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            httpBasic {}
        }
        return http.build()
    }

}

发布 BeanWebSecurityCustomizer

Spring Security 5.4 引入了 WebSecurityCustomizer 以替换 . 要准备将其删除,您可以替换如下代码:configure(WebSecurity web)WebSecurityConfigurerAdapterspring-doc.cn

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    override fun configure(val web: WebSecurity) {
        web.ignoring().antMatchers("/ignore1", "/ignore2")
    }

}
@Configuration
public class SecurityConfiguration {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}
@Configuration
open class SecurityConfiguration {

    @Bean
    fun webSecurityCustomizer(): WebSecurityCustomizer {
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2")
    }

}

发布 BeanAuthenticationManager

作为删除的一部分,也会被删除。 准备删除它会因您使用它的原因而异。WebSecurityConfigurerAdapterconfigure(AuthenticationManagerBuilder)spring-doc.cn

LDAP 身份验证

如果要用于 LDAP 身份验证支持,则可以替换:auth.ldapAuthentication()spring-doc.cn

@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);
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    override fun configure(auth: AuthenticationManagerBuilder) {
        auth
            .ldapAuthentication()
                .userDetailsContextMapper(PersonContextMapper())
                .userDnPatterns("uid={0},ou=people")
                .contextSource()
                .port(0)
    }

}
@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();
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun contextSourceFactoryBean(): EmbeddedLdapServerContextSourceFactoryBean {
        val contextSourceFactoryBean: EmbeddedLdapServerContextSourceFactoryBean =
            EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer()
        contextSourceFactoryBean.setPort(0)
        return contextSourceFactoryBean
    }

    @Bean
    fun ldapAuthenticationManager(val contextSource: BaseLdapPathContextSource): AuthenticationManager {
        val factory = LdapBindAuthenticationManagerFactory(contextSource)
        factory.setUserDnPatterns("uid={0},ou=people")
        factory.setUserDetailsContextMapper(PersonContextMapper())
        return factory.createAuthenticationManager()
    }
}

JDBC 身份验证

如果您用于 JDBC 身份验证支持,则可以替换:auth.jdbcAuthentication()spring-doc.cn

@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(this.dataSource)
                .withUser(user);
    }
}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
    @Bean
    fun dataSource(): DataSource {
        return EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build()
    }

    override fun configure(val auth: AuthenticationManagerBuilder) {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        auth.jdbcAuthentication()
            .withDefaultSchema()
                .dataSource(this.dataSource)
                .withUser(user)
    }
}
@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;
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun dataSource(): DataSource {
        return EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
            .build()
    }

    @Bean
    fun users(val dataSource: DataSource): UserDetailsManager {
        val user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        val users = JdbcUserDetailsManager(dataSource)
        users.createUser(user)
        return users
    }
}

内存中身份验证

如果使用的是 In-Memory Authentication 支持,则可以替换:auth.inMemoryAuthentication()spring-doc.cn

@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);
    }
}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
    override fun configure(val auth: AuthenticationManagerBuilder) {
        val user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        auth.inMemoryAuthentication()
            .withUser(user)
    }
}
@Configuration
public class SecurityConfiguration {
    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun userDetailsService(): InMemoryUserDetailsManager {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        return InMemoryUserDetailsManager(user)
    }
}

添加到注释@Configuration@Enable*

在 6.0 中,所有 Spring Security 的 Comments 都已删除。 虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的注释。 此外,在 Spring Framework 中引入对的支持提供了另一个原因,可以从 Spring Security 的注释中删除元注释,并允许用户选择进入他们喜欢的配置模式。@Enable*@Configuration@Enable*@Configuration(proxyBeanMethods=false)@Configuration@Enable*spring-doc.cn

以下注释已删除:@Configurationspring-doc.cn

例如,如果您使用的是 ,则需要更改:@EnableWebSecurityspring-doc.cn

@EnableWebSecurity
public class SecurityConfig {
	// ...
}
@Configuration
@EnableWebSecurity
public class SecurityConfig {
	// ...
}

这同样适用于上面列出的所有其他 Comments。spring-doc.cn

其他场景

如果你正在使用更复杂的东西,你可以发布你自己的 AuthenticationManager @Bean 或者使用 HttpSecurity#authenticationManager 将实例连接到 DSL 中。AuthenticationManagerBuilderAuthenticationManagerHttpSecurityspring-doc.cn