Kotlin Configuration

Spring Security Kotlin 配置已在 Spring Security 5.3 中提供。通过使用原生 Kotlin DSL,用户可以使用此配置配置 Spring Security。

Spring Security Kotlin configuration has been available since Spring Security 5.3. It lets users configure Spring Security by using a native Kotlin DSL.

Spring Security 提供了 a sample application 来演示 Spring Security Kotlin 配置的使用。

Spring Security provides a sample application to demonstrate the use of Spring Security Kotlin Configuration.

HttpSecurity

Spring Security 如何知道我们要要求所有用户都进行身份验证?Spring Security 如何知道我们要支持基于表单的身份验证?有一个在后台调用的配置类(名为 SecurityFilterChain)。它使用以下默认实现进行了配置:

How does Spring Security know that we want to require all users to be authenticated? How does Spring Security know we want to support form-based authentication? There is a configuration class (called SecurityFilterChain) that is being invoked behind the scenes. It is configured with the following default implementation:

import org.springframework.security.config.annotation.web.invoke

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

请务必在您的类中导入 invoke 函数,因为 IDE 并非总是自动导入该方法,从而导致编译问题。

Make sure to import the invoke function in your class, as the IDE will not always auto-import the method, causing compilation issues.

前面的列表中显示的默认配置:

The default configuration (shown in the preceding listing):

  • Ensures that any request to our application requires the user to be authenticated

  • Lets users authenticate with form-based login

  • Lets users authenticate with HTTP Basic authentication

请注意,此配置与 XML 命名空间配置并行:

Note that this configuration parallels the XML namespace configuration:

<http>
	<intercept-url pattern="/**" access="authenticated"/>
	<form-login />
	<http-basic />
</http>

Multiple HttpSecurity Instances

我们可以配置多个 HttpSecurity 实例,就像我们可以有多个 <http> 块一样。关键是注册多个 SecurityFilterChain @Bean。以下示例为以 /api/ 开头的 URL 进行了不同的配置:

We can configure multiple HttpSecurity instances, just as we can have multiple <http> blocks. The key is to register multiple SecurityFilterChain @Bean`s. The following example has a different configuration for URLs that start with `/api/:

import org.springframework.security.config.annotation.web.invoke

@Configuration
@EnableWebSecurity
class MultiHttpSecurityConfig {
    @Bean                                                            1
    public fun userDetailsService(): UserDetailsService {
        val users: User.UserBuilder = User.withDefaultPasswordEncoder()
        val manager = InMemoryUserDetailsManager()
        manager.createUser(users.username("user").password("password").roles("USER").build())
        manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build())
        return manager
    }

    @Order(1)                                                        2
    @Bean
    open fun apiFilterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            securityMatcher("/api/**")                               3
            authorizeHttpRequests {
                authorize(anyRequest, hasRole("ADMIN"))
            }
            httpBasic { }
        }
        return http.build()
    }

    @Bean                                                            4
    open fun formLoginFilterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            formLogin { }
        }
        return http.build()
    }
}
1 Configure Authentication as usual.
2 Create an instance of SecurityFilterChain that contains @Order to specify which SecurityFilterChain should be considered first.
3 The http.securityMatcher states that this HttpSecurity is applicable only to URLs that start with /api/
4 Create another instance of SecurityFilterChain. If the URL does not start with /api/, this configuration is used. This configuration is considered after apiFilterChain, since it has an @Order value after 1 (no @Order defaults to last).