|
对于最新的稳定版本,请使用 Spring Security 6.5.3! |
配置迁移
以下步骤与有关如何配置的更改有关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方法.
新的requestMatchers添加了方法自authorizeHttpRequests,authorizeRequests、CSRF配置、WebSecurityCustomizer以及任何其他有专门的地方RequestMatcher方法。
已弃用的方法已在 Spring Security 6 中删除。
这些新方法具有更安全的默认值,因为它们选择了最合适的RequestMatcher实现。
总之,新方法选择了MvcRequestMatcher如果您的应用程序在类路径中有 Spring MVC,则回退到AntPathRequestMatcher如果 Spring MVC 不存在,则实现(使行为与 Kotlin 等效方法保持一致)。
要开始使用新方法,您可以用新方法替换已弃用的方法。例如,以下应用程序配置:
-
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();
}
}
如果您在类路径中有 Spring MVC 并且正在使用mvcMatchers方法,您可以将其替换为新方法,Spring Security 将选择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();
}
}
如果您正在自定义servletPath属性的MvcRequestMatcher,您现在可以使用MvcRequestMatcher.Builder创建MvcRequestMatcher共享相同 servlet 路径的实例:
-
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();
}
}
如果您在使用新的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 中,antMatchers,mvcMatchers和requestMatchers方法 来自HttpSecurity被弃用,取而代之的是新的securityMatchers方法。
请注意,这些方法与authorizeHttpRequests被弃用的方法,取而代之的是requestMatchers方法。
但是,securityMatchers方法类似于requestMatchers方法,即他们会选择最合适的方法RequestMatcher实现。
总之,新方法选择了MvcRequestMatcher如果您的应用程序在类路径中有 Spring MVC,则回退到AntPathRequestMatcher如果 Spring MVC 不存在,则实现(使行为与 Kotlin 等效方法保持一致)。
添加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 {
// ...
}
如果您要组合多个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
发布一个SecurityFilterChain豆
Spring Security 5.4 引入了发布SecurityFilterChainbean 而不是扩展WebSecurityConfigurerAdapter.
在 6.0 中,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()
}
}
发布一个WebSecurityCustomizer豆
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")
}
}
发布一个AuthenticationManager豆
作为WebSecurityConfigurerAdapter免职configure(AuthenticationManagerBuilder)也被删除。
准备删除它会根据您使用它的原因而有所不同。
LDAP 身份验证
如果您正在使用auth.ldapAuthentication()对于 LDAP 身份验证支持,您可以替换:
-
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 身份验证
如果您正在使用auth.jdbcAuthentication()对于 JDBC 身份验证支持,您可以替换:
-
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
}
}
内存中身份验证
如果您正在使用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 的@Enable*注释具有@Configuration删除。
虽然很方便,但它与其他 Spring 项目不一致,尤其是 Spring Framework 的@Enable*附注。
此外,还引入了对@Configuration(proxyBeanMethods=false)在 Spring Framework 中提供了另一个删除@Configurationmeta-comments 来自 Spring Security 的@Enable*注释,并允许用户选择加入他们首选的配置模式。
以下注释具有@Configuration删除:
-
@EnableGlobalAuthentication -
@EnableGlobalMethodSecurity -
@EnableMethodSecurity -
@EnableReactiveMethodSecurity -
@EnableWebSecurity -
@EnableWebFluxSecurity
例如,如果您使用@EnableWebSecurity,您将需要更改:
-
Java
@EnableWebSecurity
public class SecurityConfig {
// ...
}
自:
-
Java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// ...
}
这同样适用于上面列出的所有其他注释。
其他场景
如果您正在使用AuthenticationManagerBuilder对于更复杂的东西,您可以发布您自己的AuthenticationManager @Bean或将AuthenticationManager实例转换为HttpSecurityDSL 与HttpSecurity#authenticationManager.