对于最新的稳定版本,请使用 Spring Security 6.4.1! |
配置迁移
以下步骤与有关如何配置 、 和 .HttpSecurity
WebSecurity
AuthenticationManager
添加注释@Configuration
在 6.0 中,已从 、 、 和 中删除。@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@EnableGlobalMethodSecurity
@EnableGlobalAuthentication
为此,无论您在何处使用这些注释之一,都可能需要添加 .
例如,从以下位置更改:@Configuration
@EnableMethodSecurity
-
Java
@EnableMethodSecurity
public class MyConfiguration {
// ...
}
-
Kotlin
@EnableMethodSecurity
open class MyConfiguration {
// ...
}
自:
-
Java
@Configuration
@EnableMethodSecurity
public class MyConfiguration {
// ...
}
-
Kotlin
@Configuration
@EnableMethodSecurity
open class MyConfiguration {
// ...
}
使用新方法requestMatchers
在 Spring Security 5.8 中,antMatchers
、mvcMatchers
和 regexMatchers
方法已被弃用,取而代之的是新的 requestMatchers
方法。
新方法被添加到 authorizeHttpRequests
、 、 CSRF 配置和任何其他具有专用方法的地方。
已弃用的方法在 Spring Security 6 中删除。requestMatchers
authorizeRequests
WebSecurityCustomizer
RequestMatcher
这些新方法具有更安全的默认值,因为它们为您的应用程序选择最合适的实现。
总之,如果您的应用程序在 Classpath 中有 Spring MVC,则新方法会选择实现,如果 Spring MVC 不存在,则回退到实现(使行为与 Kotlin 等效方法保持一致)。RequestMatcher
MvcRequestMatcher
AntPathRequestMatcher
要开始使用新方法,您可以将已弃用的方法替换为新方法。例如,以下应用程序配置:
-
Java
@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();
}
}
可以更改为:
-
Java
@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 将为您选择实现。
以下配置:mvcMatchers
MvcRequestMatcher
-
Java
@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();
}
}
等效于:
-
Java
@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 路径的实例:servletPath
MvcRequestMatcher
MvcRequestMatcher.Builder
MvcRequestMatcher
-
Java
@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.Builder
requestMatchers
-
Java
@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,则可以使用接受实例的方法:requestMatchers
RequestMatcher
AntPathRequestMatcher
RegexRequestMatcher
requestMatchers
RequestMatcher
-
Java
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();
}
}
请注意,上面的示例使用了 AntPathRequestMatcher
和 RegexRequestMatcher
中的静态工厂方法来提高可读性。
如果您正在使用该接口,则可以替换已弃用的方法:WebSecurityCustomizer
antMatchers
-
Java
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}
与他们的对应物:requestMatchers
-
Java
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}
同样,如果你正在自定义 CSRF 配置以忽略某些路径,你可以用方法替换已弃用的方法:requestMatchers
-
Java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf((csrf) -> csrf
.ignoringAntMatchers("/no-csrf")
);
return http.build();
}
可以更改为:
-
Java
@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,取而代之的是新方法。antMatchers
mvcMatchers
requestMatchers
HttpSecurity
securityMatchers
请注意,这些方法与已弃用以支持这些方法的方法不同。
但是,这些方法与方法相似,因为它们将为您的应用程序选择最合适的实现。
总之,如果您的应用程序在 Classpath 中有 Spring MVC,则新方法会选择实现,如果 Spring MVC 不存在,则回退到实现(使行为与 Kotlin 等效方法保持一致)。
添加方法的另一个原因是为了避免与 .authorizeHttpRequests
requestMatchers
securityMatchers
requestMatchers
RequestMatcher
MvcRequestMatcher
AntPathRequestMatcher
securityMatchers
requestMatchers
authorizeHttpRequests
以下配置:
-
Java
@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();
}
可以使用以下方法重写:securityMatchers
-
Java
@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();
}
如果您在配置中使用自定义:RequestMatcher
HttpSecurity
-
Java
@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 {
// ...
}
您可以使用以下方法执行相同的操作:securityMatcher
-
Java
@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:RequestMatcher
HttpSecurity
-
Java
@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();
}
您可以使用 :securityMatchers
-
Java
@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();
}
如果您在选择实现的方法中遇到问题,您始终可以自己选择实现:securityMatchers
RequestMatcher
RequestMatcher
-
Java
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 中,已删除。
要为此更改做好准备,您可以替换如下结构:SecurityFilterChain
WebSecurityConfigurerAdapter
WebSecurityConfigurerAdapter
-
Java
-
Kotlin
@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 {}
}
}
}
跟:
-
Java
-
Kotlin
@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)
WebSecurityConfigurerAdapter
-
Java
-
Kotlin
@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")
}
}
跟:
-
Java
-
Kotlin
@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
作为删除的一部分,也会被删除。
准备删除它会因您使用它的原因而异。WebSecurityConfigurerAdapter
configure(AuthenticationManagerBuilder)
LDAP 身份验证
如果要用于 LDAP 身份验证支持,则可以替换:auth.ldapAuthentication()
-
Java
-
Kotlin
@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)
}
}
跟:
-
Java
-
Kotlin
@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()
-
Java
-
Kotlin
@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)
}
}
跟:
-
Java
-
Kotlin
@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()
-
Java
-
Kotlin
@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)
}
}
跟:
-
Java
-
Kotlin
@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*
以下注释已删除:@Configuration
-
@EnableGlobalAuthentication
-
@EnableGlobalMethodSecurity
-
@EnableMethodSecurity
-
@EnableReactiveMethodSecurity
-
@EnableWebSecurity
-
@EnableWebFluxSecurity
例如,如果您使用的是 ,则需要更改:@EnableWebSecurity
-
Java
@EnableWebSecurity
public class SecurityConfig {
// ...
}
自:
-
Java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// ...
}
这同样适用于上面列出的所有其他 Comments。
其他场景
如果你正在使用更复杂的东西,你可以发布你自己的 AuthenticationManager
@Bean
或者使用 HttpSecurity#authenticationManager
将实例连接到 DSL 中。AuthenticationManagerBuilder
AuthenticationManager
HttpSecurity