Use GrantedAuthorityDefaults Bean in Kotlin DSL
Closes gh-15171
This commit is contained in:
parent
24e3bb11bc
commit
a7f9ccb6d6
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web
|
package org.springframework.security.config.annotation.web
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext
|
||||||
import org.springframework.http.HttpMethod
|
import org.springframework.http.HttpMethod
|
||||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager
|
import org.springframework.security.authorization.AuthenticatedAuthorizationManager
|
||||||
import org.springframework.security.authorization.AuthorityAuthorizationManager
|
import org.springframework.security.authorization.AuthorityAuthorizationManager
|
||||||
|
@ -23,10 +24,11 @@ import org.springframework.security.authorization.AuthorizationDecision
|
||||||
import org.springframework.security.authorization.AuthorizationManager
|
import org.springframework.security.authorization.AuthorizationManager
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer
|
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer
|
||||||
|
import org.springframework.security.config.core.GrantedAuthorityDefaults
|
||||||
import org.springframework.security.core.Authentication
|
import org.springframework.security.core.Authentication
|
||||||
|
import org.springframework.security.web.access.IpAddressAuthorizationManager
|
||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter
|
import org.springframework.security.web.access.intercept.AuthorizationFilter
|
||||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||||
import org.springframework.security.web.access.IpAddressAuthorizationManager
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||||
|
@ -41,7 +43,7 @@ import java.util.function.Supplier
|
||||||
* @since 5.7
|
* @since 5.7
|
||||||
* @property shouldFilterAllDispatcherTypes whether the [AuthorizationFilter] should filter all dispatcher types
|
* @property shouldFilterAllDispatcherTypes whether the [AuthorizationFilter] should filter all dispatcher types
|
||||||
*/
|
*/
|
||||||
class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
||||||
@Deprecated("""
|
@Deprecated("""
|
||||||
Add authorization rules to DispatcherType directly.
|
Add authorization rules to DispatcherType directly.
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
||||||
var shouldFilterAllDispatcherTypes: Boolean? = null
|
var shouldFilterAllDispatcherTypes: Boolean? = null
|
||||||
|
|
||||||
private val authorizationRules = mutableListOf<AuthorizationManagerRule>()
|
private val authorizationRules = mutableListOf<AuthorizationManagerRule>()
|
||||||
|
private val rolePrefix: String
|
||||||
|
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"
|
private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||||
|
@ -227,7 +230,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
||||||
* @return the [AuthorizationManager] with the provided role
|
* @return the [AuthorizationManager] with the provided role
|
||||||
*/
|
*/
|
||||||
fun hasRole(role: String): AuthorizationManager<RequestAuthorizationContext> {
|
fun hasRole(role: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||||
return AuthorityAuthorizationManager.hasRole(role)
|
return AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, arrayOf(role))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -237,7 +240,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
||||||
* @return the [AuthorizationManager] with the provided roles
|
* @return the [AuthorizationManager] with the provided roles
|
||||||
*/
|
*/
|
||||||
fun hasAnyRole(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
|
fun hasAnyRole(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||||
return AuthorityAuthorizationManager.hasAnyRole(*roles)
|
return AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, arrayOf(*roles))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -290,4 +293,18 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.rolePrefix = "ROLE_"
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: ApplicationContext) {
|
||||||
|
val beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults::class.java)
|
||||||
|
if (beanNames.size > 0) {
|
||||||
|
val grantedAuthorityDefaults = context.getBean(GrantedAuthorityDefaults::class.java);
|
||||||
|
this.rolePrefix = grantedAuthorityDefaults.rolePrefix
|
||||||
|
} else {
|
||||||
|
this.rolePrefix = "ROLE_"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||||
|
|
||||||
var authenticationManager: AuthenticationManager? = null
|
var authenticationManager: AuthenticationManager? = null
|
||||||
|
val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a [SecurityConfigurerAdapter] to this [HttpSecurity]
|
* Applies a [SecurityConfigurerAdapter] to this [HttpSecurity]
|
||||||
|
@ -298,7 +299,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||||
* @since 5.7
|
* @since 5.7
|
||||||
*/
|
*/
|
||||||
fun authorizeHttpRequests(authorizeHttpRequestsConfiguration: AuthorizeHttpRequestsDsl.() -> Unit) {
|
fun authorizeHttpRequests(authorizeHttpRequestsConfiguration: AuthorizeHttpRequestsDsl.() -> Unit) {
|
||||||
val authorizeHttpRequestsCustomizer = AuthorizeHttpRequestsDsl().apply(authorizeHttpRequestsConfiguration).get()
|
val authorizeHttpRequestsCustomizer = AuthorizeHttpRequestsDsl(this.context).apply(authorizeHttpRequestsConfiguration).get()
|
||||||
this.http.authorizeHttpRequests(authorizeHttpRequestsCustomizer)
|
this.http.authorizeHttpRequests(authorizeHttpRequestsCustomizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web
|
package org.springframework.security.config.annotation.web
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions.*
|
import jakarta.servlet.DispatcherType
|
||||||
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import org.springframework.beans.factory.UnsatisfiedDependencyException
|
import org.springframework.beans.factory.UnsatisfiedDependencyException
|
||||||
|
@ -28,6 +29,7 @@ import org.springframework.security.authorization.AuthorizationDecision
|
||||||
import org.springframework.security.authorization.AuthorizationManager
|
import org.springframework.security.authorization.AuthorizationManager
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||||
|
import org.springframework.security.config.core.GrantedAuthorityDefaults
|
||||||
import org.springframework.security.config.test.SpringTestContext
|
import org.springframework.security.config.test.SpringTestContext
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension
|
import org.springframework.security.config.test.SpringTestContextExtension
|
||||||
import org.springframework.security.core.Authentication
|
import org.springframework.security.core.Authentication
|
||||||
|
@ -55,7 +57,6 @@ import org.springframework.web.servlet.config.annotation.PathMatchConfigurer
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||||
import org.springframework.web.util.WebUtils
|
import org.springframework.web.util.WebUtils
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import jakarta.servlet.DispatcherType
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for [AuthorizeHttpRequestsDsl]
|
* Tests for [AuthorizeHttpRequestsDsl]
|
||||||
|
@ -835,7 +836,6 @@ class AuthorizeHttpRequestsDslTests {
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
open class HasIpAddressConfig {
|
open class HasIpAddressConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
|
@ -853,4 +853,43 @@ class AuthorizeHttpRequestsDslTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun `hasRole when prefixed by configured role prefix should fail to configure`() {
|
||||||
|
assertThatThrownBy { this.spring.register(RoleValidationConfig::class.java).autowire() }
|
||||||
|
.isInstanceOf(UnsatisfiedDependencyException::class.java)
|
||||||
|
.hasRootCauseInstanceOf(IllegalArgumentException::class.java)
|
||||||
|
.hasMessageContaining(
|
||||||
|
"ROLE_JUNIPER should not start with ROLE_ since ROLE_ is automatically prepended when using hasAnyRole. Consider using hasAnyAuthority instead."
|
||||||
|
)
|
||||||
|
assertThatThrownBy { this.spring.register(RoleValidationConfig::class.java, GrantedAuthorityDefaultsConfig::class.java).autowire() }
|
||||||
|
.isInstanceOf(UnsatisfiedDependencyException::class.java)
|
||||||
|
.hasRootCauseInstanceOf(IllegalArgumentException::class.java)
|
||||||
|
.hasMessageContaining(
|
||||||
|
"CUSTOM_JUNIPER should not start with CUSTOM_ since CUSTOM_ is automatically prepended when using hasAnyRole. Consider using hasAnyAuthority instead."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
open class RoleValidationConfig {
|
||||||
|
@Bean
|
||||||
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
|
http {
|
||||||
|
authorizeHttpRequests {
|
||||||
|
authorize("/role", hasAnyRole("ROLE_JUNIPER"))
|
||||||
|
authorize("/custom", hasRole("CUSTOM_JUNIPER"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return http.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
open class GrantedAuthorityDefaultsConfig {
|
||||||
|
@Bean
|
||||||
|
open fun grantedAuthorityDefaults(): GrantedAuthorityDefaults {
|
||||||
|
return GrantedAuthorityDefaults("CUSTOM_")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue