对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

以下步骤与有关如何配置 、 和 的更改相关。HttpSecurityWebSecurityAuthenticationManagerSpring中文文档

添加批注@Configuration

在 6.0 中,从 、 、 和 中删除。@Configuration@EnableWebSecurity@EnableMethodSecurity@EnableGlobalMethodSecurity@EnableGlobalAuthenticationSpring中文文档

为此,无论您在哪里使用这些注释之一,您可能需要添加 . 例如,更改为:@Configuration@EnableMethodSecuritySpring中文文档

@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中文文档

新方法已添加到 authorizeHttpRequests、CSRF 配置以及具有专用方法的任何其他位置。 在 Spring Security 6 中删除了已弃用的方法。requestMatchersauthorizeRequestsWebSecurityCustomizerRequestMatcherSpring中文文档

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

若要开始使用新方法,可以将已弃用的方法替换为新方法。例如,以下应用程序配置:Spring中文文档

@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中文文档

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

}

如果您的类路径中有 Spring MVC 并且正在使用这些方法,则可以将其替换为新方法,Spring Security 将为您选择实现。 配置如下:mvcMatchersMvcRequestMatcherSpring中文文档

@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中文文档

@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中文文档

@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中文文档

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

}

如果新方法有问题,可以随时切换回正在使用的实现。 例如,如果仍要使用 和 实现,则可以使用接受实例的方法:requestMatchersRequestMatcherAntPathRequestMatcherRegexRequestMatcherrequestMatchersRequestMatcherSpring中文文档

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中文文档

如果您使用的是该接口,则可以替换已弃用的方法:WebSecurityCustomizerantMatchersSpring中文文档

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

与同行:requestMatchersSpring中文文档

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

同样,如果要自定义 CSRF 配置以忽略某些路径,则可以将已弃用的方法替换为以下方法:requestMatchersSpring中文文档

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

可以更改为:Spring中文文档

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

使用新方法securityMatchers

在 Spring Security 5.8 中,弃用了 和 from 的方法,取而代之的是新方法。antMatchersmvcMatchersrequestMatchersHttpSecuritysecurityMatchersSpring中文文档

请注意,这些方法与已弃用的方法不同,而这些方法已弃用。 但是,这些方法与方法类似,因为它们将为您的应用程序选择最合适的实现。 总之,如果您的应用程序在类路径中具有 Spring MVC,则新方法会选择实现,如果不存在 Spring MVC,则回退到实现(使行为与 Kotlin 等效方法保持一致)。 添加方法的另一个原因是避免与 中的方法混淆。authorizeHttpRequestsrequestMatcherssecurityMatchersrequestMatchersRequestMatcherMvcRequestMatcherAntPathRequestMatchersecurityMatchersrequestMatchersauthorizeHttpRequestsSpring中文文档

配置如下:Spring中文文档

@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中文文档

@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中文文档

@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中文文档

@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 {
	// ...
}

如果要在配置中组合多个实现:RequestMatcherHttpSecuritySpring中文文档

@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中文文档

@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中文文档

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 而不是扩展 Bean 的功能。 在 6.0 中,被删除。 若要准备此更改,可以替换如下构造:SecurityFilterChainWebSecurityConfigurerAdapterWebSecurityConfigurerAdapterSpring中文文档

@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中文文档

@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中文文档

LDAP 身份验证

如果用于 LDAP 身份验证支持,则可以将:auth.ldapAuthentication()Spring中文文档

@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中文文档

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

内存中身份验证

如果用于内存中身份验证支持,则可以替换:auth.inMemoryAuthentication()Spring中文文档

@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 的所有注解都被删除了。 虽然方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的注解。 此外,在 Spring Framework 中引入对 的支持提供了另一个原因,可以从 Spring Security 的注解中删除元注解,并允许用户选择他们喜欢的配置模式。@Enable*@Configuration@Enable*@Configuration(proxyBeanMethods=false)@Configuration@Enable*Spring中文文档

删除了以下注释:@ConfigurationSpring中文文档

例如,如果您正在使用 ,则需要更改:@EnableWebSecuritySpring中文文档

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

这同样适用于上面列出的所有其他注释。Spring中文文档

其他方案

如果您使用的是更复杂的内容,则可以发布自己的 AuthenticationManager @Bean,或者使用 HttpSecurity#authenticationManager 将实例连接到 DSL。AuthenticationManagerBuilderAuthenticationManagerHttpSecuritySpring中文文档